From af477398d2a20fd30e28b5228552d9a8449ab913 Mon Sep 17 00:00:00 2001 From: Robbert Bos Date: Sat, 31 Jan 2026 18:06:04 +0100 Subject: [PATCH] feat(deploy): add wait-for-ready feature Add optional health checking to wait for deployments to be reachable before continuing. New inputs: - wait-for-ready: enable waiting (default: false) - health-endpoint: path to check (default: /) - wait-timeout: max wait time in seconds (default: 300) - wait-interval: time between checks (default: 10) Also updates README: - Add wait-for-ready documentation and examples - Replace manual health check script with built-in feature - Use generic example URLs instead of specific domains - Format tables for better readability --- CHANGELOG.md | 5 ++++ deploy/README.md | 71 +++++++++++++++++++---------------------------- deploy/action.yml | 45 ++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e249b00..2777ee1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `.github/dependabot.yml` for automated GitHub Actions updates - `.gitignore` for local settings and Claude plans - `.claude/` configuration for AI assistant (coding rules, skills, workflow) +- **deploy** action: Wait for ready feature + - Wait for deployment to be reachable before continuing + - New inputs: `wait-for-ready`, `health-endpoint`, `wait-timeout`, `wait-interval` + - Polls deployment URL until HTTP 2xx/3xx or timeout + - PR comment only appears after deployment is healthy (when combined with `comment-on-pr`) ### Changed - `.pre-commit-config.yaml`: require minimum version 4.5.0 diff --git a/deploy/README.md b/deploy/README.md index 0748673..eb1fa3f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -17,11 +17,15 @@ Deploys a container image to ZAD Operations Manager. | `comment-on-pr` | No | `false` | Post/update a comment on the PR with the deployment URL | | `github-token` | No | `github.token` | GitHub token for PR commenting (defaults to automatic token) | | `comment-header` | No | `## 🚀 Preview Deployment` | Custom header for the PR comment | +| `wait-for-ready` | No | `false` | Wait for deployment to be reachable | +| `health-endpoint` | No | `/` | Endpoint to check for readiness | +| `wait-timeout` | No | `300` | Maximum wait time in seconds | +| `wait-interval` | No | `10` | Seconds between readiness checks | ## Outputs -| Name | Description | -|------|-------------| +| Name | Description | +|-------|---------------------------------| | `url` | URL of the deployed application | ## Example Usage @@ -30,17 +34,13 @@ Deploys a container image to ZAD Operations Manager. ```yaml - name: Deploy to ZAD - id: deploy uses: RijksICTGilde/zad-actions/deploy@v1 with: api-key: ${{ secrets.ZAD_API_KEY }} - project-id: regel-k4c + project-id: my-project deployment-name: production - component: editor - image: ghcr.io/minbzk/regelrecht-mvp:latest - -- name: Show deployment URL - run: echo "Deployed to ${{ steps.deploy.outputs.url }}" + component: web + image: ghcr.io/org/app:latest ``` ### PR Preview with Cloned Config @@ -51,11 +51,11 @@ Deploys a container image to ZAD Operations Manager. uses: RijksICTGilde/zad-actions/deploy@v1 with: api-key: ${{ secrets.ZAD_API_KEY }} - project-id: regel-k4c + project-id: my-project deployment-name: pr${{ github.event.pull_request.number }} - component: editor - image: ghcr.io/minbzk/regelrecht-mvp:pr-${{ github.event.number }} - clone-from: production + component: web + image: ghcr.io/org/app:${{ github.sha }} + clone-from: development ``` ### PR Preview with Automatic Comment @@ -76,8 +76,8 @@ deploy-preview: project-id: my-project deployment-name: pr${{ github.event.pull_request.number }} component: web - image: ghcr.io/org/app:pr-${{ github.event.number }} - clone-from: production + image: ghcr.io/org/app:${{ github.sha }} + clone-from: development comment-on-pr: true ``` @@ -87,7 +87,7 @@ The action will create a comment like this on the PR: > > Your changes have been deployed to a preview environment: > -> **URL:** https://web-pr123-my-project.rig.prd1.gn2.quattro.rijksapps.nl +> **URL:** https://web-pr85-my-project.your-domain.example.com > > This deployment will be automatically cleaned up when the PR is closed. @@ -110,15 +110,15 @@ deploy: project-id: my-project deployment-name: pr${{ github.event.pull_request.number }} component: web - image: ghcr.io/org/app:pr-${{ github.event.number }} + image: ghcr.io/org/app:${{ github.sha }} ``` ## Permissions -| Feature | Required Permission | -|---------|---------------------| -| Basic deployment | None (only ZAD API key) | -| PR commenting | `pull-requests: write` | +| Feature | Required Permission | +|------------------|---------------------------| +| Basic deployment | None (only ZAD API key) | +| PR commenting | `pull-requests: write` | For PR commenting, ensure your job has the required permission (the token defaults to `github.token`): @@ -131,12 +131,12 @@ permissions: The output URL follows the standard ZAD pattern: ``` -https://{component}-{deployment}-{project}.rig.prd1.gn2.quattro.rijksapps.nl +https://{component}-{deployment}-{project}.your-domain.example.com ``` For example: -- `component: editor`, `deployment: pr73`, `project: regel-k4c` -- URL: `https://editor-pr73-regel-k4c.rig.prd1.gn2.quattro.rijksapps.nl` +- `component: web`, `deployment: pr85`, `project: my-project` +- URL: `https://web-pr85-my-project.your-domain.example.com` ### Multi-Component Deployment @@ -167,8 +167,8 @@ Deploy to different environments based on branch: deploy: runs-on: ubuntu-latest steps: - - name: Deploy to staging - if: github.ref == 'refs/heads/develop' + - name: Deploy to preview + if: github.ref == 'refs/heads/staging' uses: RijksICTGilde/zad-actions/deploy@v1 with: api-key: ${{ secrets.ZAD_API_KEY }} @@ -186,16 +186,14 @@ deploy: deployment-name: production component: web image: ghcr.io/org/app:${{ github.sha }} - clone-from: staging ``` ### Deploy with Deployment Status Check -Wait for deployment to be healthy: +Wait for deployment to be healthy using the built-in `wait-for-ready` feature: ```yaml - name: Deploy to ZAD - id: deploy uses: RijksICTGilde/zad-actions/deploy@v1 with: api-key: ${{ secrets.ZAD_API_KEY }} @@ -203,19 +201,8 @@ Wait for deployment to be healthy: deployment-name: production component: web image: ghcr.io/org/app:latest - -- name: Wait for deployment to be ready - run: | - for i in {1..30}; do - if curl -s -o /dev/null -w "%{http_code}" "${{ steps.deploy.outputs.url }}/health" | grep -q "200"; then - echo "Deployment is healthy!" - exit 0 - fi - echo "Waiting for deployment... (attempt $i/30)" - sleep 10 - done - echo "Deployment health check timed out" - exit 1 + wait-for-ready: true + health-endpoint: /health ``` ## How It Works diff --git a/deploy/action.yml b/deploy/action.yml index ddda836..32af567 100644 --- a/deploy/action.yml +++ b/deploy/action.yml @@ -47,6 +47,22 @@ inputs: description: 'Custom header for the PR comment (default: "## 🚀 Preview Deployment")' required: false default: '## 🚀 Preview Deployment' + wait-for-ready: + description: 'Wait for deployment to be reachable before continuing' + required: false + default: 'false' + health-endpoint: + description: 'Endpoint to check for readiness (e.g., /, /health)' + required: false + default: '/' + wait-timeout: + description: 'Maximum time to wait for deployment in seconds' + required: false + default: '300' + wait-interval: + description: 'Seconds between readiness checks' + required: false + default: '10' outputs: url: @@ -181,6 +197,35 @@ runs: exit 1 fi + - name: Wait for deployment to be ready + if: inputs.wait-for-ready == 'true' + shell: bash + env: + DEPLOYMENT_URL: ${{ steps.deploy.outputs.url }} + HEALTH_ENDPOINT: ${{ inputs.health-endpoint }} + WAIT_TIMEOUT: ${{ inputs.wait-timeout }} + WAIT_INTERVAL: ${{ inputs.wait-interval }} + run: | + URL="${DEPLOYMENT_URL}${HEALTH_ENDPOINT}" + echo "Waiting for $URL to be ready..." + + ELAPSED=0 + while [ "$ELAPSED" -lt "$WAIT_TIMEOUT" ]; do + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$URL" || echo "000") + + if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 400 ]; then + echo "Deployment is ready (HTTP $HTTP_CODE)" + exit 0 + fi + + echo "Waiting... (HTTP $HTTP_CODE, ${ELAPSED}s elapsed)" + sleep "$WAIT_INTERVAL" + ELAPSED=$((ELAPSED + WAIT_INTERVAL)) + done + + echo "::error::Deployment did not become ready within ${WAIT_TIMEOUT}s" + exit 1 + - name: Comment on PR if: inputs.comment-on-pr == 'true' && github.event_name == 'pull_request' shell: bash