Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

βœ… E2E on K8S Stack πŸš€πŸš€πŸš€ #48

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 68 additions & 58 deletions .github/workflows/impress-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,6 @@ jobs:
path: 'src/frontend/**/node_modules'
key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }}

build-front:
runs-on: ubuntu-latest
needs: install-front
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Restore the frontend cache
uses: actions/cache@v4
id: front-node_modules
with:
path: 'src/frontend/**/node_modules'
key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }}

- name: Build CI App
run: cd src/frontend/ && yarn ci:build

- name: Cache build frontend
uses: actions/cache@v4
with:
path: src/frontend/apps/impress/out/
key: build-front-${{ github.run_id }}

test-front:
runs-on: ubuntu-latest
needs: install-front
Expand Down Expand Up @@ -100,52 +77,85 @@ jobs:

test-e2e:
runs-on: ubuntu-latest
needs: build-front
timeout-minutes: 10
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set services env variables
run: |
make data/media
make create-env-files
cat env.d/development/common.e2e.dist >> env.d/development/common

- name: Restore the frontend cache
uses: actions/cache@v4
id: front-node_modules
with:
path: 'src/frontend/**/node_modules'
key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }}

- name: Restore the build cache
uses: actions/cache@v4
id: cache-build
with:
path: src/frontend/apps/impress/out/
key: build-front-${{ github.run_id }}

- name: Build and Start Docker Servers
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
- name: Install K8S Stacks
run: |
docker-compose build --pull --build-arg BUILDKIT_INLINE_CACHE=1
make run

- name: Apply DRF migrations
run: |
make migrate

- name: Add dummy data
# Install Tilt
sudo curl -fsSL https://github.com/tilt-dev/tilt/releases/download/v0.33.12/tilt.0.33.12.linux-alpine.x86_64.tar.gz | tar -xzv tilt
sudo mv tilt /usr/local/bin/tilt

# Install kubectl
sudo curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
sudo kubectl version --client

# Install Helm
sudo curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
helm plugin install https://github.com/databus23/helm-diff
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.0
sudo curl -fsSL https://github.com/helmfile/helmfile/releases/download/v0.163.1/helmfile_0.163.1_linux_amd64.tar.gz | tar -xzv helmfile
sudo mv helmfile /usr/local/bin/helmfile

# Install mkcert
sudo curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64"
sudo chmod +x mkcert-v*-linux-amd64
sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert

# Install kind
sudo [ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
sudo chmod +x ./kind
sudo cp ./kind /usr/local/bin/kind
sudo rm -rf kind

# Install sops
sudo curl -LO https://github.com/getsops/sops/releases/download/v3.8.1/sops-v3.8.1.linux.amd64
sudo mv sops-v3.8.1.linux.amd64 /usr/local/bin/sops
sudo chmod +x /usr/local/bin/sops

- name: Start Kind
run: bash bin/start-kind.sh

- name: Wait for all pods to be ready
run: |
make demo FLUSH_ARGS='--no-input'
# Continuously check until all pods are ready or until timeout
for i in {1..30}; do # attempts for up to 5 minutes
NOT_READY=$(kubectl get pods -A --no-headers | awk '$4 != "Running" && $4 != "Completed" {print $1, $2, $4}')
if [ -z "$NOT_READY" ]; then
echo "All pods are in the desired state (Running or Completed)."
break
else
echo "Waiting for all pods to be in Running or Completed state. Current statuses of pods not ready:"
echo "$NOT_READY"
sleep 10
fi
done

# Final check, if still not ready, print and exit with error
if [ ! -z "$NOT_READY" ]; then
echo "Timeout reached. The following pods are not in Running or Completed state:"
echo "$NOT_READY"
exit 1
fi

echo "Wait a bit more to ensure all services are up"
sleep 15

- name: Start servers
env:
SOPS_AGE_KEY: ${{ secrets.SOPS_PRIVATE }}
run: tilt ci --debug --verbose -f ./bin/TiltfileE2E

- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install

- name: Run e2e tests
env:
AGENT_CONNECT_SIGNIN: true
BASE_URL: https://impress.127.0.0.1.nip.io
run: cd src/frontend/ && yarn e2e:test

- uses: actions/upload-artifact@v3
Expand Down
2 changes: 1 addition & 1 deletion bin/Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ docker_build(
]
)

k8s_yaml(local('cd ../src/helm && helmfile -n impress -e dev template .'))
k8s_yaml(local('cd ../src/helm && helmfile -n impress --state-values-set "localDev=true" -e dev template .'))

migration = '''
set -eu
Expand Down
41 changes: 41 additions & 0 deletions bin/TiltfileE2E
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
load('ext://namespace', 'namespace_create', 'namespace_inject')
namespace_create('impress')

docker_build(
'localhost:5001/impress-backend:latest',
context='..',
dockerfile='../Dockerfile',
only=['./src/backend', './src/mail', './docker'],
target = 'backend-development',
live_update=[
sync('../src/backend', '/app'),
run(
'pip install -r /app/requirements.txt',
trigger=['./api/requirements.txt']
)
]
)

docker_build(
'localhost:5001/impress-y-webrtc-signaling:latest',
context='..',
dockerfile='../src/frontend/Dockerfile',
only=['./src/frontend/', './docker/', './dockerignore'],
target = 'y-webrtc-signaling',
live_update=[
sync('../src/frontend', '/home/frontend'),
]
)

docker_build(
'localhost:5001/impress-frontend:latest',
context='..',
dockerfile='../src/frontend/Dockerfile',
only=['./src/frontend', './docker', './dockerignore'],
target = 'frontend-production',
live_update=[
sync('../src/frontend', '/home/frontend'),
]
)

k8s_yaml(local('cd ../src/helm && helmfile -n impress --state-values-set "localDev=false" -e dev template .'))
1 change: 1 addition & 0 deletions src/frontend/apps/e2e/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
test-results/
report/
blob-report/
playwright/.auth/
playwright/.cache/
8 changes: 4 additions & 4 deletions src/frontend/apps/e2e/__tests__/app-impress/404.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { expect, test } from '@playwright/test';

import { keyCloakSignIn } from './common';

test.beforeEach(async ({ page, browserName }) => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await keyCloakSignIn(page, browserName);
await expect(
page.locator('header').first().locator('h2').getByText('Impress'),
).toBeVisible();
await page.goto('unknown-page404');
});

Expand Down
11 changes: 11 additions & 0 deletions src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test as setup } from '@playwright/test';

import { signIn } from './common';

const authFile = 'playwright/.auth/user.json';

setup('authenticate', async ({ page, browserName }) => {
await page.goto('/');
await signIn(page, browserName);
await page.context().storageState({ path: authFile });
});
37 changes: 31 additions & 6 deletions src/frontend/apps/e2e/__tests__/app-impress/common.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
import { Page, expect } from '@playwright/test';

import { conf } from './conf';

export const signIn = async (page: Page, browserName: string) => {
const AGENT_CONNECT_SIGNIN = process.env.AGENT_CONNECT_SIGNIN === 'true';

AGENT_CONNECT_SIGNIN
? await agentConnectSignIn(page)
: await keyCloakSignIn(page, browserName);
};

export const agentConnectSignIn = async (page: Page) => {
const title = await page.locator('h1').first().textContent({
timeout: 5000,
});

if (title?.includes('Se connecter Γ  Impress')) {
await page.getByLabel('Email professionnel').fill(conf.loginAgentConnect);
await page.getByRole('button', { name: 'Se connecter' }).click();

await page
.getByLabel('Renseignez votre mot de passe')
.fill(conf.passwordAgentConnect);
await page.getByRole('button', { name: 'S’identifier' }).click();
}
};

export const keyCloakSignIn = async (page: Page, browserName: string) => {
const title = await page.locator('h1').first().textContent({
timeout: 5000,
});

if (title?.includes('Sign in to your account')) {
await page
.getByRole('textbox', { name: 'username' })
.fill(`user-e2e-${browserName}`);
const login = `user-e2e-${browserName}`;
const password = `password-e2e-${browserName}`;

await page
.getByRole('textbox', { name: 'password' })
.fill(`password-e2e-${browserName}`);
await page.getByRole('textbox', { name: 'username' }).fill(login);

await page.getByRole('textbox', { name: 'password' }).fill(password);

await page.click('input[type="submit"]', { force: true });
}
Expand Down
4 changes: 4 additions & 0 deletions src/frontend/apps/e2e/__tests__/app-impress/conf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const conf = {
loginAgentConnect: '[email protected]',
passwordAgentConnect: 'e2e-Testing',
};
5 changes: 1 addition & 4 deletions src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { expect, test } from '@playwright/test';

import { keyCloakSignIn } from './common';

test.beforeEach(async ({ page, browserName }) => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await keyCloakSignIn(page, browserName);
});

test.describe('Header', () => {
Expand Down
5 changes: 1 addition & 4 deletions src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { expect, test } from '@playwright/test';

import { keyCloakSignIn } from './common';

test.beforeEach(async ({ page, browserName }) => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await keyCloakSignIn(page, browserName);
});

test.describe('Language', () => {
Expand Down
75 changes: 0 additions & 75 deletions src/frontend/apps/e2e/__tests__/app-impress/menu.spec.ts

This file was deleted.

Loading
Loading