name: Build and test on: push: branches: - main pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: REGISTRY: ghcr.io APP_IMAGE_NAME: ${{ github.repository }} NGINX_IMAGE_NAME: ${{ github.repository }}-nginx jobs: build: runs-on: ubuntu-latest permissions: contents: write packages: write pull-requests: write actions: write steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata for application image id: meta-app uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.APP_IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=pr type=sha,prefix={{branch}}-,enable={{is_default_branch}} type=raw,value=latest,enable={{is_default_branch}} - name: Extract metadata for nginx image id: meta-nginx uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.NGINX_IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=pr type=sha,prefix={{branch}}-,enable={{is_default_branch}} type=raw,value=latest,enable={{is_default_branch}} - name: Build application image uses: docker/build-push-action@v5 with: context: . file: docker/production/Dockerfile load: true tags: kompass:test cache-from: | type=gha,scope=app-${{ github.ref_name }} type=gha,scope=app-master type=gha,scope=app-main type=registry,ref=ghcr.io/${{ github.repository }}:latest cache-to: type=gha,mode=max,scope=app-${{ github.ref_name }} build-args: | BUILDKIT_INLINE_CACHE=1 - name: Build documentation run: | # Create output directory with proper permissions mkdir -p docs-output chmod 777 docs-output # Run sphinx-build inside the container docker run --rm \ -v ${{ github.workspace }}/docs:/app/docs:ro \ -v ${{ github.workspace }}/docs-output:/app/docs-output \ kompass:test \ bash -c "cd /app/docs && sphinx-build -b html source /app/docs-output" - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs-output destination_dir: ${{ github.ref == 'refs/heads/main' && '.' || github.head_ref || github.ref_name }} keep_files: true - name: Comment documentation link if: github.event_name == 'pull_request' uses: marocchino/sticky-pull-request-comment@v2 with: header: deployment message: | 📚 **Documentation deployed!** **Documentation:** https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{ github.head_ref }}/ **Docker Images:** - App: `${{ env.REGISTRY }}/${{ env.APP_IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}` - Nginx: `${{ env.REGISTRY }}/${{ env.NGINX_IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}` Add the `awaiting-deployment` label to deploy this PR to a staging server. - name: Run tests run: make test-only - name: Check coverage run: | COVERAGE=$(python3 -c "import json; data=json.load(open('docker/test/htmlcov/coverage.json')); print(data['totals']['percent_covered'])") echo "Coverage: ${COVERAGE}%" if (( $(echo "$COVERAGE < 100" | bc -l) )); then echo "Error: Coverage is ${COVERAGE}%, must be 100%" exit 1 fi - name: Tag and push application image run: | # Tag the built image with all required tags echo "${{ steps.meta-app.outputs.tags }}" | while read -r tag; do docker tag kompass:test "$tag" docker push "$tag" done - name: Build and push nginx image uses: docker/build-push-action@v5 with: context: docker/production/nginx file: docker/production/nginx/Dockerfile push: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} cache-from: | type=gha,scope=nginx-${{ github.ref_name }} type=gha,scope=nginx-master type=gha,scope=nginx-main type=registry,ref=ghcr.io/${{ github.repository }}-nginx:latest cache-to: type=gha,mode=max,scope=nginx-${{ github.ref_name }} build-args: | BUILDKIT_INLINE_CACHE=1 - name: Output image tags run: | echo "Application image tags:" echo "${{ steps.meta-app.outputs.tags }}" echo "" echo "Nginx image tags:" echo "${{ steps.meta-nginx.outputs.tags }}" - name: Check for awaiting-deployment label and trigger deploy if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const prNumber = context.payload.pull_request.number; // Check if PR has awaiting-deployment label const { data: pr } = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber }); const hasLabel = pr.labels.some(label => label.name === 'awaiting-deployment'); if (hasLabel) { console.log('PR has awaiting-deployment label, triggering deployment'); await github.rest.actions.createWorkflowDispatch({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: 'deploy-pr.yml', ref: context.payload.pull_request.head.ref, inputs: { pr_number: prNumber.toString() } }); } else { console.log('PR does not have awaiting-deployment label, skipping deployment'); }