Skip to content

chore(deps): lock file maintenance #204

chore(deps): lock file maintenance

chore(deps): lock file maintenance #204

name: Geti Tune UI checks
on:
workflow_dispatch:
push:
branches:
- develop
- releases/**
tags:
- "v*"
pull_request:
merge_group:
branches:
- develop
- releases/**
permissions: {} # No permissions by default on workflow level
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.after }}
cancel-in-progress: true
jobs:
# Determines if workflow should execute based on event type and changed paths
# If push or workflow_dispatch -> always run
# If PR or merge_group -> run only if files in specified paths changed
check_paths:
name: Check if workflow should run
runs-on: ubuntu-latest
outputs:
run_workflow: ${{ steps.run_workflow.outputs.run }}
steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Get all paths that should trigger the workflow
id: changed-files-yaml
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
with:
files_yaml: |
test:
- application/backend/**
- application/ui/**
- .github/**
- name: Set run flag
id: run_workflow
run: |
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "run=true" >> "$GITHUB_OUTPUT"
elif [ "${{ steps.changed-files-yaml.outputs.test_any_changed }}" = "true" ]; then
echo "run=true" >> "$GITHUB_OUTPUT"
else
echo "run=false" >> "$GITHUB_OUTPUT"
fi
generate-openapi-spec:
name: Generate OpenAPI Spec
runs-on: ubuntu-latest
needs: check_paths
if: needs.check_paths.outputs.run_workflow == 'true'
permissions:
contents: read # to checkout code
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: "3.13"
- name: Install uv
uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v6.7.0
with:
version: "0.8.8"
enable-cache: false
- name: Install OpenCV dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgl1 libglib2.0-0
- name: Prepare venv and install Python dependencies
working-directory: application/backend
run: |
uv lock --check
uv sync --frozen --all-extras
- name: Get OpenAPI spec
working-directory: application/backend
run: |
export PYTHONPATH=.
uv run app/cli.py gen-api --target-path openapi-spec.json
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: openapi-spec
path: application/backend/openapi-spec.json
build:
name: Build UI
runs-on: ubuntu-latest
needs: check_paths
if: needs.check_paths.outputs.run_workflow == 'true'
permissions:
contents: read # to checkout code
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
id: setup-node
with:
node-version-file: application/ui/.nvmrc
- name: Install dependencies
working-directory: "application/ui"
run: npm ci
- name: Build UI
working-directory: "application/ui"
run: npm run build
- name: Compress build
working-directory: "application/ui"
run: tar -czf dist.tar.gz dist
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ui-dist
path: "application/ui/dist.tar.gz"
lint:
name: Eslint checks
runs-on: ubuntu-latest
needs:
- check_paths
- generate-openapi-spec
if: needs.check_paths.outputs.run_workflow == 'true'
permissions:
contents: read # to checkout code
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
id: setup-node
with:
node-version-file: application/ui/.nvmrc
- name: Install dependencies
working-directory: "application/ui"
run: npm ci
- name: Download OpenAPI spec artifact
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: openapi-spec
path: application/ui/src/api
- name: Build OpenAPI type definitions
working-directory: "application/ui"
run: npm run build:api
- name: Prettier
working-directory: "application/ui"
run: npm run format:check
- name: Eslint
working-directory: "application/ui"
run: npm run lint
- name: Eslint cyclic imports
working-directory: "application/ui"
run: npm run cyclic-deps-check
- name: Typescript
working-directory: "application/ui"
run: npm run type-check
unit-tests:
name: Unit tests
runs-on: ubuntu-latest
needs:
- check_paths
- generate-openapi-spec
if: needs.check_paths.outputs.run_workflow == 'true'
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
id: setup-node
with:
node-version-file: application/ui/.nvmrc
- name: Install dependencies
working-directory: "application/ui"
run: npm ci
- name: Download OpenAPI spec artifact
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: openapi-spec
path: application/ui/src/api
- name: Build OpenAPI type definitions
working-directory: "application/ui"
run: npm run build:api
- name: UI Unit tests
working-directory: "application/ui"
run: npm run test:unit:coverage
- name: Generate coverage report
if: github.event.pull_request.head.repo.full_name == github.repository
working-directory: "application/ui"
run: |
echo "## 📊 Test coverage report" > coverage.md
if [ -f "coverage/coverage-summary.json" ]; then
node -e "
const fs = require('fs');
try {
const coverage = JSON.parse(fs.readFileSync('./coverage/coverage-summary.json', 'utf8'));
const lines = \`\${coverage.total.lines.pct.toFixed(1)}%\`;
const functions = \`\${coverage.total.functions.pct.toFixed(1)}%\`;
const branches = \`\${coverage.total.branches.pct.toFixed(1)}%\`;
const statements = \`\${coverage.total.statements.pct.toFixed(1)}%\`;
console.log(\`| Metric | Coverage |\`);
console.log(\`| --- | --- |\`);
console.log(\`| Lines | \${lines} |\`);
console.log(\`| Functions | \${functions} |\`);
console.log(\`| Branches | \${branches} |\`);
console.log(\`| Statements | \${statements} |\`);
} catch {
console.error('Failed to parse coverage summary');
}
" >> coverage.md
else
echo "No coverage summary found" >> coverage.md
fi
- name: Comment PR with coverage report
if: github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
const fs = require('fs');
let coverageComment = '';
try {
coverageComment = fs.readFileSync('application/ui/coverage.md', 'utf8');
} catch (error) {
coverageComment = '## 📊 Test Coverage Report\n\nCoverage report generation failed.';
}
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const existingComment = comments.data.find((comment) => comment.body.includes("Test coverage report"));
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: coverageComment
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: coverageComment
});
}
playwright-tests:
name: Playwright Tests
needs:
- check_paths
- build
- generate-openapi-spec
if: needs.check_paths.outputs.run_workflow == 'true'
permissions:
contents: read # to checkout code
timeout-minutes: 60
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.54.0-noble@sha256:18d6adb6aaccf1b0f30eba890069972e089138e4a59ddb5303d7e7290e4e38b6
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
ref: ${{ inputs.ref || '' }}
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
id: setup-node
with:
node-version-file: application/ui/.nvmrc
- name: Install dependencies
working-directory: "application/ui"
run: npm ci
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: ui-dist
path: "application/ui"
- name: Unpack build
working-directory: "application/ui"
run: tar -xzf dist.tar.gz
- name: Download OpenAPI spec artifact
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: openapi-spec
path: application/ui/src/api
- name: Build OpenAPI type definitions
working-directory: "application/ui"
run: npm run build:api
- name: Run Playwright tests
working-directory: "application/ui"
run: npm run test:component -- --project "Component tests"
- name: Upload blob report to GitHub Actions Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: playwright-report
path: application/ui/playwright-report/
retention-days: 30
required_check:
name: Required Check ui-lint-and-test
needs:
- check_paths
- generate-openapi-spec
- build
- lint
- unit-tests
- playwright-tests
runs-on: ubuntu-latest
env:
CHECKS: ${{ join(needs.*.result, ' ') }}
if: always() && !cancelled()
steps:
- name: Check jobs results
run: |
for check in ${CHECKS}; do
echo "::notice::check=${check}"
if [[ "$check" != "success" && "$check" != "skipped" ]]; then
echo "::error ::Required status checks failed. They must succeed before this pull request can be merged."
exit 1
fi
done