From 9c1936daff7eb2bb309326e1a934a68ba3ed6e23 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 00:50:16 +0000 Subject: [PATCH 1/2] chore(deps): update github/codeql-action digest to b96794f --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4c6fe72..064e08f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -52,15 +52,15 @@ jobs: go-version-file: go.mod cache-dependency-path: go.sum - - uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4 + - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 with: languages: ${{ matrix.language }} queries: security-and-quality - - uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4 + - uses: github/codeql-action/autobuild@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 - id: codeql_analyze - uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4 + uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 with: category: "/language:${{ matrix.language }}" output: sarif-results/${{ matrix.language }} From 18bb144d8fe2564196e6a950390d8ee882f86616 Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Mon, 14 Sep 2026 07:16:13 -0400 Subject: [PATCH 2/2] fix: trigger CI on development instead of blocking promotion ci.yml only ran on push/PR to main, so a plain push to development (including sync-development.yml's fast-forward/reset) never produced a CI run to find. The weekly promotion workflow was blocking on a health check that could never be satisfied. Add workflow_dispatch to ci.yml and have promote-dev-to-main.yml dispatch a run against development and poll for it when no completed run already exists. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_015sQmLYL3pTG8H9farrgyRs --- .github/workflows/ci.yml | 1 + .github/workflows/promote-dev-to-main.yml | 49 +++++++++++++++-------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0bb40e..5e6df26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: branches: [main] pull_request: branches: [main] + workflow_dispatch: {} permissions: contents: read diff --git a/.github/workflows/promote-dev-to-main.yml b/.github/workflows/promote-dev-to-main.yml index 2541d22..0aab6b7 100644 --- a/.github/workflows/promote-dev-to-main.yml +++ b/.github/workflows/promote-dev-to-main.yml @@ -31,6 +31,7 @@ env: permissions: contents: read pull-requests: write + actions: write jobs: check-development-health: @@ -61,17 +62,12 @@ jobs: const headSha = branch.commit.sha; core.info(`development HEAD: ${headSha}`); - // sync-development.yml never creates a new commit — development is always - // either untouched or fast-forwarded/reset to development's exact - // SHA. So a completed CI run on 'development' at this same SHA is - // equally valid proof of health, and covers two gaps in checking - // 'development' alone: (1) if development was synced with the GITHUB_TOKEN - // fallback (doesn't trigger downstream workflows), CI never ran on - // development at all; (2) if development already matched development when - // the sync ran, no push happened, so no development-branch run exists - // for this SHA even with a trigger token configured. - let run = null; - for (let attempt = 1; attempt <= 4; attempt += 1) { + // ci.yml only triggers on push/PR to main, so a plain push to development + // (including sync-development.yml's fast-forward/reset) never produces a + // CI run on its own. Rather than blocking promotion on a run that will + // never show up, dispatch one against development explicitly and wait + // for it to finish. + async function findCompletedRun(since) { const { data } = await github.rest.actions.listWorkflowRuns({ owner: context.repo.owner, repo: context.repo.repo, @@ -79,18 +75,37 @@ jobs: status: 'completed', per_page: 20, }); - run = data.workflow_runs.find( - (r) => r.head_sha === headSha && (r.head_branch === 'development' || r.head_branch === 'development'), + return data.workflow_runs.find( + (r) => r.head_sha === headSha && (!since || new Date(r.created_at) >= since), ); - if (run) break; - core.info(`No completed CI run for development HEAD yet (attempt ${attempt}/4), waiting...`); - await new Promise((resolve) => setTimeout(resolve, 15000)); + } + + let run = await findCompletedRun(); + + if (!run) { + core.info('No completed CI run for development HEAD — triggering one via workflow_dispatch'); + const dispatchTime = new Date(Date.now() - 5000); // small buffer for clock skew + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'ci.yml', + ref: 'development', + }); + + const POLL_INTERVAL_MS = 20000; + const MAX_ATTEMPTS = 30; // ~10 minutes + for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt += 1) { + await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS)); + run = await findCompletedRun(dispatchTime); + if (run) break; + core.info(`Waiting for triggered CI run to complete (attempt ${attempt}/${MAX_ATTEMPTS})...`); + } } if (!run) { core.setOutput('is_healthy', 'false'); core.setOutput('run_url', `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/workflows/ci.yml`); - core.warning('No completed CI run found for development HEAD — blocking promotion'); + core.warning('Triggered CI run for development HEAD did not complete in time — blocking promotion'); return; }