Skip to content

ci(deploy): wait for docker-publish before firing homelab webhook - #437

Merged
LucasSantana-Dev merged 2 commits into
mainfrom
ci/fix-deploy-race-condition
Apr 1, 2026
Merged

LucasSantana-Dev merged 2 commits into
mainfrom
ci/fix-deploy-race-condition

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented Apr 1, 2026 •

Copy link
Copy Markdown
Owner

Problem

deploy.yml and docker-publish.yml both trigger on push to main and run in parallel. The deploy job fires the homelab webhook ~4 seconds after the push, while Docker images take 2–6 minutes to build. deploy.sh then runs docker pull latest and gets stale images — homelab never receives the new code.

Timeline from the last push:

Event Time (UTC)
Webhook fired 02:32:51Z
nginx image ready 02:33:16Z (+25s)
frontend image ready 02:34:46Z (+2m)
bot image ready 02:37:48Z (+5m)
backend image ready 02:38:21Z (+5.5m)

Fix

Add a "Wait for Docker images" step in deploy.yml (before the webhook trigger) that:

  1. Checks if docker-publish.yml is running for the same commit SHA via the GitHub API
  2. If not found → no Docker changes in this push, proceeds immediately
  3. If in progress → polls every 15s until completed (up to 10 min timeout)
  4. If docker-publish failed → aborts the deploy to avoid deploying with broken images

Behavior

  • Pushes with Docker changes: deploy waits ~5min for images, then fires webhook with fresh latest tags
  • Pushes without Docker changes (docs, config, etc.): deploy fires immediately as before
  • workflow_dispatch: no docker-publish run for that SHA → fires immediately

Summary by CodeRabbit

  • Chores
    • Deployment pipeline now waits for Docker image publishing to complete before deploying, polling for completion and proceeding only when the publish succeeds.
    • Deployment will abort if image publishing fails or times out, reducing failed releases.
    • Workflow permissions tightened to use a more restricted token scope for safer pipeline operations.

Deploy and docker-publish both trigger on push to main, causing a
race condition where deploy.sh pulls stale 'latest' images. Add a
polling step that waits up to 10min for docker-publish to complete
before firing the homelab webhook. Skips the wait when no Docker
changes are present in the push.
@vercel

vercel Bot commented Apr 1, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment Apr 1, 2026 4:08am

Request Review

@coderabbitai

coderabbitai Bot commented Apr 1, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ad2ac46-fefd-4688-8b83-9795040a4280

📥 Commits

Reviewing files that changed from the base of the PR and between 4f91e2e and 4740db0.

📒 Files selected for processing (1)
  • .github/workflows/deploy.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/deploy.yml

📝 Walkthrough

Walkthrough

Adds a workflow step to the deploy GitHub Actions workflow that locates the most recent docker-publish.yml run for the current commit via GH CLI/jq, then polls that run until it completes (success/failure) or a timeout, and gates deployment on the run's conclusion.

Changes

Cohort / File(s) Summary
Deployment workflow
.github/workflows/deploy.yml
Added job-level permissions: actions: read and a new Wait for Docker images step that: finds the latest docker-publish.yml run matching github.sha, exits early if none found within initial window, otherwise polls gh run view up to a 600s max_wait and succeeds only if the run completes with conclusion=success; fails on other conclusions or timeout.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant DeployWF as Deploy Workflow
    participant GHCLI as GH CLI (gh)
    participant ActionsAPI as GitHub Actions API
    participant DockerPublish as docker-publish run

    DeployWF->>GHCLI: gh run list (filter by workflow docker-publish & headSha)
    GHCLI->>ActionsAPI: request runs list
    ActionsAPI-->>GHCLI: returns runs metadata
    alt no matching run within initial window
        GHCLI-->>DeployWF: no run found -> exit success (proceed deploy)
    else matching run found
        GHCLI->>ActionsAPI: gh run view <run-id> (poll until status=completed or timeout)
        loop polling (up to max_wait)
            ActionsAPI-->>GHCLI: status / conclusion updates
        end
        alt conclusion == success
            GHCLI-->>DeployWF: success -> allow deploy
        else conclusion != success or timeout
            GHCLI-->>DeployWF: fail -> abort deploy
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a wait step for docker-publish workflow before firing the homelab webhook to fix a race condition.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/fix-deploy-race-condition

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/deploy.yml (1)

34-35: Harden GH CLI for stream-friendly logs

Set GH_PAGER=cat (or equivalent) to guarantee non-paged CLI output in CI logs.

As per coding guidelines, "Ensure logs are stream-friendly (no pagers) in scripts; when a pager might be used, pipe to cat".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy.yml around lines 34 - 35, The workflow run step
currently sets the shell flags with "set -euo pipefail" but does not enforce
non-paged GH CLI output; update the same run block (the step containing the "set
-euo pipefail" line) to set GH_PAGER=cat for the environment used by the GH CLI
so logs are stream-friendly—e.g., export or prefix GH_PAGER=cat before invoking
gh commands in that run step (ensure the change is applied in the run block that
contains "set -euo pipefail").
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy.yml:
- Around line 32-34: The deploy workflow fails under hardened repo permissions
because the "Wait for Docker images" step uses the GitHub CLI commands (gh run
list / gh run view) but the GITHUB_TOKEN (GH_TOKEN) lacks actions:read scope;
update the workflow to grant actions: read to the job or workflow by adding a
permissions block that includes actions: read so the GH_TOKEN used in the "Wait
for Docker images" step can call gh run list and gh run view without 403 errors.
- Around line 52-55: The workflow currently exits immediately when run_info is
empty, causing a race; modify the block that checks run_info (the result of the
`gh run list` query for the `docker-publish` workflow) to poll up to 60 seconds
(e.g., 12 attempts with 5s sleeps) re-running the `gh run list` check each
attempt and breaking early if a `docker-publish` run appears; if after the
timeout no run is found then proceed with the existing exit 0 branch. Use the
existing variable name run_info and the same `gh run list` query for detection,
and ensure the loop has a bounded retry count so it never blocks indefinitely.

---

Nitpick comments:
In @.github/workflows/deploy.yml:
- Around line 34-35: The workflow run step currently sets the shell flags with
"set -euo pipefail" but does not enforce non-paged GH CLI output; update the
same run block (the step containing the "set -euo pipefail" line) to set
GH_PAGER=cat for the environment used by the GH CLI so logs are
stream-friendly—e.g., export or prefix GH_PAGER=cat before invoking gh commands
in that run step (ensure the change is applied in the run block that contains
"set -euo pipefail").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 97c6cfa1-c0a1-4311-8bef-610edcc91abd

📥 Commits

Reviewing files that changed from the base of the PR and between f38ead1 and 4f91e2e.

📒 Files selected for processing (1)
  • .github/workflows/deploy.yml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: SonarCloud Scan
  • GitHub Check: Quality Gates
🧰 Additional context used
📓 Path-based instructions (7)
**/{.github/workflows,}/*.{yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/ci-cd.mdc)

**/{.github/workflows,}/*.{yml,yaml}: CI pipeline must include setup step (node install, environment)
CI pipeline must include lint step (TypeScript typecheck + linter)
CI pipeline must include build step (production build)
CI pipeline must include test step (unit + integration) with coverage report
CI pipeline must include quality step (static analysis, vulnerability scan)

Files:

  • .github/workflows/deploy.yml
**/{.github/workflows,dependabot.yml}/*.{yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/ci-cd.mdc)

Configure dependency update bot with PR templates and tests (recommended)

Files:

  • .github/workflows/deploy.yml
**/.github/workflows/*.{yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/ci-cd.mdc)

**/.github/workflows/*.{yml,yaml}: Configure SAST / secrets scan on PRs (recommended)
Publish artifacts only from protected pipeline steps

Files:

  • .github/workflows/deploy.yml
{jest.config.*,*.coverage.*,.nycrc*,nyc.config.*,coveragerc,.github/workflows/*.yml,.github/workflows/*.yaml}

📄 CodeRabbit inference engine (.cursor/rules/testing-quality.mdc)

Minimum recommended coverage threshold: 85% (raise per project risk)

Files:

  • .github/workflows/deploy.yml
{.github/workflows/*.{yml,yaml},*.github/workflows/*.{yml,yaml},.gitlab-ci.yml,.circleci/config.yml,bitbucket-pipelines.yml}

📄 CodeRabbit inference engine (.cursor/rules/testing-quality.mdc)

CI must run in order: lint → build → test → quality checks

Files:

  • .github/workflows/deploy.yml
{.github/workflows/**/*.{yml,yaml},**/.gitlab-ci.yml,.circleci/config.yml}

📄 CodeRabbit inference engine (.cursor/rules/workflow.mdc)

{.github/workflows/**/*.{yml,yaml},**/.gitlab-ci.yml,.circleci/config.yml}: CI/CD pipeline must include in order: Setup (Node install, env config) → Lint (TypeScript typecheck, linter) → Build (production build, artifacts) → Test (unit, integration, coverage) → Quality (static analysis, vulnerability scan)
Publish artifacts only from protected pipeline steps in CI/CD

Files:

  • .github/workflows/deploy.yml
{**/scripts/**,scripts/**,.github/workflows/**/*.{yml,yaml},**/.gitlab-ci.yml,.circleci/config.yml}

📄 CodeRabbit inference engine (.cursor/rules/workflow.mdc)

{**/scripts/**,scripts/**,.github/workflows/**/*.{yml,yaml},**/.gitlab-ci.yml,.circleci/config.yml}: Use cross-platform environment handling in scripts, cross-platform deletion utilities instead of OS-specific commands, pass non-interactive flags (--yes, --ci) by default in automation, and avoid OS-specific commands
Ensure logs are stream-friendly (no pagers) in scripts; when a pager might be used, pipe to cat

Files:

  • .github/workflows/deploy.yml

Comment thread .github/workflows/deploy.yml
Comment thread .github/workflows/deploy.yml
@sonarqubecloud

sonarqubecloud Bot commented Apr 1, 2026

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 4ad1d9b into main Apr 1, 2026
12 checks passed
@LucasSantana-Dev LucasSantana-Dev mentioned this pull request Apr 1, 2026
3 tasks
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
* ci(deploy): wait for docker-publish before firing webhook

Deploy and docker-publish both trigger on push to main, causing a
race condition where deploy.sh pulls stale 'latest' images. Add a
polling step that waits up to 10min for docker-publish to complete
before firing the homelab webhook. Skips the wait when no Docker
changes are present in the push.

* ci(deploy): fix permissions, pager, and detect polling
@LucasSantana-Dev
LucasSantana-Dev deleted the ci/fix-deploy-race-condition branch May 23, 2026 02:21

This branch was successfully deployed

1 active deployment
Preview — 4740db08 Deployed Apr 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant