feat(editor): merge harvester-admin into the editor as a gated Beheer section #4780
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Build and Deploy | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| types: [opened, synchronize, reopened, closed, labeled] | |
| permissions: {} | |
| env: | |
| REGISTRY: ghcr.io | |
| ZAD_PROJECT: regel-k4c | |
| jobs: | |
| changes: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| if: >- | |
| github.event.action != 'closed' && | |
| (github.event.action != 'labeled' || startsWith(github.event.label.name, 'deploy:')) | |
| permissions: | |
| contents: read | |
| outputs: | |
| editor: ${{ steps.filter.outputs.editor }} | |
| admin: ${{ steps.filter.outputs.admin }} | |
| harvester-worker: ${{ steps.filter.outputs.harvester-worker }} | |
| enrich-worker: ${{ steps.filter.outputs.enrich-worker }} | |
| pipeline-api: ${{ steps.filter.outputs.pipeline-api }} | |
| grafana: ${{ steps.filter.outputs.grafana }} | |
| lawmaking: ${{ steps.filter.outputs.lawmaking }} | |
| docs: ${{ steps.filter.outputs.docs }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 | |
| id: filter | |
| with: | |
| filters: | | |
| editor: | |
| - 'frontend/**' | |
| - 'packages/frontend-shared/**' | |
| - 'packages/editor-api/**' | |
| - 'packages/engine/**' | |
| - 'packages/corpus/**' | |
| - 'packages/shared/**' | |
| - 'packages/Cargo.lock' | |
| - 'corpus-registry.yaml' | |
| - 'corpus/regulation/**' | |
| admin: | |
| - 'packages/admin/**' | |
| - 'packages/frontend-shared/**' | |
| - 'packages/pipeline/**' | |
| - 'packages/corpus/**' | |
| - 'packages/harvester/**' | |
| - 'packages/shared/**' | |
| - 'packages/Cargo.lock' | |
| harvester-worker: | |
| - 'packages/pipeline/**' | |
| - 'packages/harvester/**' | |
| - 'packages/corpus/**' | |
| - 'packages/shared/**' | |
| - 'packages/Cargo.lock' | |
| enrich-worker: | |
| - 'packages/pipeline/**' | |
| - 'packages/corpus/**' | |
| - 'packages/harvester/**' | |
| - 'packages/shared/**' | |
| - 'packages/Cargo.lock' | |
| - '.claude/skills/law-*/**' | |
| pipeline-api: | |
| - 'packages/pipeline/**' | |
| - 'packages/corpus/**' | |
| - 'packages/harvester/**' | |
| - 'packages/shared/**' | |
| - 'packages/Cargo.lock' | |
| grafana: | |
| - 'packages/grafana/**' | |
| lawmaking: | |
| - 'frontend-lawmaking/**' | |
| - 'packages/frontend-shared/**' | |
| docs: | |
| - 'docs/**' | |
| # -- Build jobs -- | |
| build: | |
| needs: changes | |
| if: >- | |
| github.event.action != 'closed' && | |
| ( | |
| needs.changes.outputs.editor == 'true' || | |
| contains(github.event.pull_request.labels.*.name, 'deploy:editor') | |
| ) | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-editor | |
| dockerfile: frontend/Dockerfile | |
| cache-scope: editor | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| build-admin: | |
| needs: changes | |
| if: github.event.action != 'closed' && needs.changes.outputs.admin == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-admin | |
| dockerfile: packages/admin/Dockerfile | |
| cache-scope: admin | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| build-harvester-worker: | |
| needs: changes | |
| if: github.event.action != 'closed' && needs.changes.outputs.harvester-worker == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-harvester-worker | |
| dockerfile: packages/pipeline/Dockerfile | |
| target: harvester-worker | |
| build-args: BIN=regelrecht-harvest-worker | |
| cache-scope: harvester-worker | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| build-enrich-worker: | |
| needs: changes | |
| if: >- | |
| github.event.action != 'closed' && | |
| ( | |
| needs.changes.outputs.enrich-worker == 'true' || | |
| contains(github.event.pull_request.labels.*.name, 'deploy:enrich-worker') | |
| ) | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-enrich-worker | |
| dockerfile: packages/pipeline/Dockerfile | |
| target: enrich-worker | |
| build-args: BIN=regelrecht-enrich-worker | |
| cache-scope: enrich-worker | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| build-pipeline-api: | |
| needs: changes | |
| if: github.event.action != 'closed' && needs.changes.outputs.pipeline-api == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-pipeline-api | |
| dockerfile: packages/pipeline/Dockerfile | |
| target: pipeline-api | |
| build-args: BIN=regelrecht-pipeline-api | |
| cache-scope: pipeline-api | |
| build-grafana: | |
| needs: changes | |
| if: >- | |
| github.ref == 'refs/heads/main' && github.event_name == 'push' && | |
| needs.changes.outputs.grafana == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-grafana | |
| dockerfile: packages/grafana/Dockerfile | |
| context: ./packages/grafana | |
| cache-scope: grafana | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| build-lawmaking: | |
| needs: changes | |
| if: github.event.action != 'closed' && needs.changes.outputs.lawmaking == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-lawmaking | |
| dockerfile: frontend-lawmaking/Dockerfile | |
| cache-scope: lawmaking | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| build-docs: | |
| needs: changes | |
| if: github.event.action != 'closed' && needs.changes.outputs.docs == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| uses: ./.github/workflows/build-image.yml | |
| with: | |
| image-name: minbzk/regelrecht-docs | |
| dockerfile: docs/Dockerfile | |
| cache-scope: docs | |
| # Only GITHUB_TOKEN is needed; it is automatically available to called workflows | |
| # -- Deploy preview -- | |
| deploy-preview: | |
| runs-on: ubuntu-latest | |
| # Each ZAD component deploy takes ~5 minutes and they run sequentially; | |
| # a PR touching engine + frontend + docs redeploys 6+ components, which | |
| # does not fit in 15 minutes. | |
| timeout-minutes: 45 | |
| needs: [build, build-admin, build-harvester-worker, build-enrich-worker, build-pipeline-api, build-lawmaking, build-docs, changes] | |
| if: >- | |
| always() && | |
| github.event_name == 'pull_request' && github.event.action != 'closed' && | |
| !cancelled() && | |
| ( | |
| needs.build.result == 'success' || | |
| needs.build-admin.result == 'success' || | |
| needs.build-harvester-worker.result == 'success' || | |
| needs.build-enrich-worker.result == 'success' || | |
| needs.build-pipeline-api.result == 'success' || | |
| needs.build-lawmaking.result == 'success' || | |
| needs.build-docs.result == 'success' | |
| ) | |
| permissions: | |
| pull-requests: write | |
| environment: | |
| name: pr${{ github.event.pull_request.number }} | |
| url: ${{ steps.deploy.outputs.url }} | |
| steps: | |
| - name: Get short SHA | |
| id: sha | |
| run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT | |
| - name: Deploy admin to ZAD (Preview) | |
| if: needs.build-admin.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: harvester-admin | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-admin:sha-${{ steps.sha.outputs.short }} | |
| domain-format: component-deployment-project | |
| clone-from: regelrecht | |
| force-clone: false | |
| comment-on-pr: true | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| comment-header: '## Preview Deployment' | |
| - name: Deploy harvester-worker to ZAD (Preview) | |
| if: needs.build-harvester-worker.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: harvester-worker | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-harvester-worker:sha-${{ steps.sha.outputs.short }} | |
| domain-format: component-deployment-project | |
| clone-from: regelrecht | |
| force-clone: false | |
| comment-on-pr: true | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| comment-header: '## Preview Deployment' | |
| - name: Deploy enrich-worker to ZAD (Preview) | |
| if: needs.build-enrich-worker.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: enrichworker | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-enrich-worker:sha-${{ steps.sha.outputs.short }} | |
| domain-format: component-deployment-project | |
| clone-from: regelrecht | |
| force-clone: false | |
| comment-on-pr: true | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| comment-header: '## Preview Deployment' | |
| - name: Deploy pipeline-api to ZAD (Preview) | |
| if: needs.build-pipeline-api.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: pipelineapi | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-pipeline-api:sha-${{ steps.sha.outputs.short }} | |
| # No public domain: pipeline-api has no authentication and is only | |
| # reachable in-cluster by editor-api (which enforces auth). Matches | |
| # the production deploy below. | |
| clone-from: regelrecht | |
| force-clone: false | |
| - name: Deploy editor to ZAD (Preview) | |
| if: needs.build.result == 'success' | |
| id: deploy | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: editor | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-editor:sha-${{ steps.sha.outputs.short }} | |
| domain-format: component-deployment-project | |
| clone-from: regelrecht | |
| force-clone: false | |
| comment-on-pr: true | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| comment-header: '## Preview Deployment — editor' | |
| - name: Deploy lawmaking to ZAD (Preview) | |
| if: needs.build-lawmaking.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: lawmaking | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-lawmaking:sha-${{ steps.sha.outputs.short }} | |
| domain-format: component-deployment-project | |
| clone-from: regelrecht | |
| force-clone: false | |
| comment-on-pr: true | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| comment-header: '## Preview Deployment — lawmaking' | |
| - name: Deploy docs to ZAD (Preview) | |
| if: needs.build-docs.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| component: docs | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-docs:sha-${{ steps.sha.outputs.short }} | |
| domain-format: component-deployment-project | |
| clone-from: regelrecht | |
| force-clone: false | |
| comment-on-pr: true | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| comment-header: '## Preview Deployment — docs' | |
| # -- Deploy production -- | |
| deploy-production: | |
| runs-on: ubuntu-latest | |
| # Same budget as deploy-preview: sequential ZAD deploys of all changed | |
| # components do not fit in 15 minutes on a broad merge. | |
| timeout-minutes: 45 | |
| needs: [build, build-admin, build-harvester-worker, build-enrich-worker, build-pipeline-api, build-grafana, build-lawmaking, build-docs] | |
| if: >- | |
| always() && | |
| github.ref == 'refs/heads/main' && github.event_name == 'push' && | |
| !cancelled() && | |
| ( | |
| needs.build.result == 'success' || | |
| needs.build-admin.result == 'success' || | |
| needs.build-harvester-worker.result == 'success' || | |
| needs.build-enrich-worker.result == 'success' || | |
| needs.build-pipeline-api.result == 'success' || | |
| needs.build-grafana.result == 'success' || | |
| needs.build-lawmaking.result == 'success' || | |
| needs.build-docs.result == 'success' | |
| ) | |
| permissions: {} | |
| environment: | |
| name: production | |
| url: ${{ steps.deploy.outputs.url }} | |
| steps: | |
| - name: Get short SHA | |
| id: sha | |
| run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT | |
| - name: Deploy admin to ZAD (Production) | |
| if: needs.build-admin.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: harvester-admin | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-admin:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy pipeline-api to ZAD (Production) | |
| if: needs.build-pipeline-api.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: pipelineapi | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-pipeline-api:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy editor to ZAD (Production) | |
| if: needs.build.result == 'success' | |
| id: deploy | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: editor | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-editor:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy harvester-worker to ZAD (Production) | |
| if: needs.build-harvester-worker.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: harvester-worker | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-harvester-worker:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy enrich-worker to ZAD (Production) | |
| if: needs.build-enrich-worker.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: enrichworker | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-enrich-worker:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy grafana to ZAD (Production) | |
| if: needs.build-grafana.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: grafana | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-grafana:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy lawmaking to ZAD (Production) | |
| if: needs.build-lawmaking.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: lawmaking | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-lawmaking:sha-${{ steps.sha.outputs.short }} | |
| - name: Deploy docs to ZAD (Production) | |
| if: needs.build-docs.result == 'success' | |
| uses: RijksICTGilde/zad-actions/deploy@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: regelrecht | |
| component: docs | |
| image: ${{ env.REGISTRY }}/minbzk/regelrecht-docs:sha-${{ steps.sha.outputs.short }} | |
| # -- Cleanup preview -- | |
| cleanup-preview: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| if: github.event_name == 'pull_request' && github.event.action == 'closed' | |
| permissions: | |
| packages: write | |
| deployments: write | |
| pull-requests: write | |
| steps: | |
| - name: Cleanup ZAD deployment and container images | |
| uses: RijksICTGilde/zad-actions/cleanup@v4 | |
| with: | |
| api-key: ${{ secrets.RIG_API_KEY }} | |
| project-id: ${{ env.ZAD_PROJECT }} | |
| deployment-name: pr${{ github.event.pull_request.number }} | |
| delete-github-env: true | |
| delete-github-deployments: true | |
| delete-container: true | |
| containers: >- | |
| [ | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-editor", "tag": "pr-${{ github.event.pull_request.number }}"}, | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-admin", "tag": "pr-${{ github.event.pull_request.number }}"}, | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-harvester-worker", "tag": "pr-${{ github.event.pull_request.number }}"}, | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-enrich-worker", "tag": "pr-${{ github.event.pull_request.number }}"}, | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-pipeline-api", "tag": "pr-${{ github.event.pull_request.number }}"}, | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-lawmaking", "tag": "pr-${{ github.event.pull_request.number }}"}, | |
| {"org": "${{ github.repository_owner }}", "name": "regelrecht-docs", "tag": "pr-${{ github.event.pull_request.number }}"} | |
| ] | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| github-admin-token: ${{ secrets.ADMIN_TOKEN }} | |
| comment-header: '## Preview Deployment' | |
| - name: Prune orphaned SHA-tagged images | |
| env: | |
| GH_TOKEN: ${{ secrets.ADMIN_TOKEN }} | |
| run: | | |
| for PACKAGE in regelrecht-editor regelrecht-admin regelrecht-harvester-worker regelrecht-enrich-worker regelrecht-pipeline-api regelrecht-grafana regelrecht-lawmaking regelrecht-docs; do | |
| echo "Pruning sha-only images for $PACKAGE..." | |
| gh api --paginate \ | |
| "/orgs/${{ github.repository_owner }}/packages/container/${PACKAGE}/versions" \ | |
| --jq '.[] | select( | |
| (.metadata.container.tags | length == 0) or | |
| (.metadata.container.tags | all(startswith("sha-"))) | |
| ) | .id' \ | |
| 2>/dev/null | while read -r VERSION_ID; do | |
| echo "Deleting $PACKAGE version $VERSION_ID" | |
| gh api --method DELETE \ | |
| "/orgs/${{ github.repository_owner }}/packages/container/${PACKAGE}/versions/${VERSION_ID}" \ | |
| 2>/dev/null || true | |
| done | |
| done |