fix(ci): three CI workflow optimizations - #74
Conversation
The default GITHUB_TOKEN cannot push to branches protected by branch-protection rules. Using the RenovateBot-SumoLogic GitHub App (already used in this org) to mint a short-lived token that has the required bypass permission on main.
Docs PRs add a CHANGELOG entry with a link to the upcoming release tag before that tag exists. The link checker returns 404 and fails the PR. Release tags are immutable once created, so skipping live HTTP checks on them is safe. Any genuine typo in a tag URL would be caught by the release-tag workflow itself failing to push.
Three problems in pull-request-checks.yml: - markdown-link-check had no job-level if guard so it ran on every PR - yamllint referenced a non-existent 'chart-changed' output (typo), always silently skipping but still spinning up a runner - terraform-lint ran unconditionally regardless of whether any .tf files changed Fixes: - Add a terraform-changed job that detects .tf/.tfvars changes - Add if guard to markdown-link-check at the job level - Fix yamllint to reference docs-changed instead of chart-changed - Gate terraform-lint on terraform-changed
24a14eb to
4e0001b
Compare
Branch protection matches checks by name. Two gating styles gave different results: - A job that an `if` condition skips reports a `skipped` conclusion. Branch protection accepts this. - A workflow that `on.pull_request.paths` skips reports no check run at all. Branch protection waits for it forever. The three `pr-build-*` workflows used path filters, so a docs-only PR left six required contexts pending and blocked the merge. A job-level `if` cannot replace the path filter directly, because those jobs call reusable workflows and the nested check names do not exist when the call is skipped. Each `pr-build-*` workflow now runs on every PR, moves the file test into a `changes` job, and ends with a plain aggregator job that always reports. `pull-request-checks.yml` gets the same aggregator. Also move the four lint guards in `pull-request-checks.yml` from step level to job level, so those jobs no longer start a runner to do nothing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`actions/upload-artifact@v4` rejects a name that contains a forward slash. The PR build workflows built the artifact name from `github.head_ref`, so every branch with a slash in its name, for example `fix/ci-optimizations`, failed the build before it compiled any code. Use `github.run_id`-`github.run_attempt`, which is always plain digits. The attempt number gives each re-run a new namespace, because an artifact name cannot be reused. `ARTIFACT_NAME` only names and finds artifacts. Layer names and bucket names come from `github.run_id`, so they do not change. The release workflows keep `github.ref_name`, because a tag name has no slash. This matches the same fix in PR #72, so the two branches do not disagree. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Resolve conflicts in pr-build-{java,nodejs,python}.yml: take
ARTIFACT_NAME: ${{ github.run_id }} from main (PR 72), which
dropped run_attempt to fix partial re-run artifact lookup failures.
There was a problem hiding this comment.
🟡 Changes recommended
Newly added workflows introduce additional uses of an unpinned third-party action tag (tj-actions/changed-files@v44), which should be pinned to an immutable commit SHA to reduce supply-chain risk.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates GitHub Actions workflows and CI tooling configs to address multiple CI reliability/branch-protection issues (release tagging permissions, docs link checking, and PR check/run gating) so required checks consistently report and unnecessary runners aren’t started.
Changes:
- Use a GitHub App token in
release-tag.ymlso the workflow can push a changelog commit and tag to protectedmain. - Adjust docs-related CI behavior: ignore unreleased
releases/tag/links and gate docs lint/link jobs at the job level (plus add an aggregator check). - Remove
paths-based PR build skipping and replace it with achangesjob + always-reporting*-completeaggregator checks for Java/NodeJS/Python PR builds.
File summaries
| File | Description |
|---|---|
.yamllint.yaml |
Relaxes YAML line-length limit to reduce lint noise. |
.markdown_link_check.json |
Ignores GitHub release-tag URLs to prevent link-check failures on unreleased tags. |
.github/workflows/release-tag.yml |
Generates a GitHub App token and uses it for checkout/push to protected main. |
.github/workflows/release-build-python.yml |
Removes trailing whitespace in workflow content block. |
.github/workflows/release-build-nodejs.yml |
Removes trailing whitespace in workflow content block. |
.github/workflows/release-build-java.yml |
Removes trailing whitespace in workflow content block. |
.github/workflows/pull-request-checks.yml |
Moves docs guards to job-level if and adds a required-check aggregator job. |
.github/workflows/publish-release-layer.yml |
Minor formatting adjustment in the matrix list. |
.github/workflows/pr-build-python.yml |
Adds changes gating and a pr-build-python-complete aggregator check. |
.github/workflows/pr-build-nodejs.yml |
Adds changes gating and a pr-build-nodejs-complete aggregator check. |
.github/workflows/pr-build-java.yml |
Adds changes gating and a pr-build-java-complete aggregator check. |
.github/labeler.yml |
Normalizes YAML inline array formatting for label rules. |
Review details
- Files reviewed: 11/12 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Mutable tags can be retargeted silently. tj-actions/changed-files had a supply-chain incident in 2025 where a tag was hijacked to exfiltrate secrets. Pinning to an immutable commit SHA prevents a future tag retarget from changing CI behaviour. Also upgrades from v44 to v47.0.6. No breaking changes to the inputs or outputs used (files, files_ignore, any_changed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The switch to a GitHub App token for tag pushes can cause duplicate release-build runs because release-build workflows already trigger on push.tags and release-tag.yml also dispatches them explicitly.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
.github/workflows/release-tag.yml:50
- Switching the tag push to a GitHub App token means the subsequent
git pushwill now emit normalpushevents for tags, sorelease-build-*.yml(which already runs onpush.tags) may start automatically; the latergh workflow run ... --ref "${TAG}"step can then trigger a second, duplicate release build run for the same tag. Consider removing the manual dispatch, or removing thepush.tagstrigger from the release-build workflows so each tag produces exactly one release build.
.markdown_link_check.json:17 - The new ignorePatterns entry is treated as a regex, so unescaped dots in "github.com" match any character and the missing start anchor can ignore unintended URLs. Escaping the dots and anchoring the pattern makes the ignore rule precise to the intended release-tag links.
- Files reviewed: 11/12 changed files
- Comments generated: 0 new
- Review effort level: Lite
Both addressed.
|
There was a problem hiding this comment.
🔵 Needs a closer look
It changes multiple GitHub Actions workflows in ways that can affect required status checks and release automation, so a final human verification of CI behavior is warranted.
Review details
- Files reviewed: 11/12 changed files
- Comments generated: 1
- Review effort level: Lite
What and why
Five independent CI issues found while working on the nodejs v2.1.0 release.
1.
release-tag.ymlcannot push tomain(run)Branch-protection rules apply to the default
GITHUB_TOKEN, so it cannot push directly tomain. Therelease-tag.ymlworkflow pushes a changelog commit and a release tag after a prepare PR merges. Both pushes fail with a 403.Fix: add a
Generate GitHub App tokenstep that usesactions/create-github-app-token@v3with theRenovateBot-SumoLogicGitHub App. The org already uses this App through theRENOVATE_APP_IDandRENOVATE_PRIVATE_KEYsecrets. The App has the necessary bypass permission onmain.2.
markdown-link-checkfails on docs PRs because of unreleased tag links (run)CHANGELOG.mdcontains a link to the next release tag, for examplereleases/tag/nodejs-v2.1.0, before that tag exists. The link checker makes a live HTTP request, gets a 404, and fails the PR.Fix: ignore
releases/tag/URLs in.markdown_link_check.json. Release tags do not change after creation, so a live check gives no value. If the tag name is wrong,release-tag.ymlfails to push and shows the error.3. Lint jobs start a runner to do nothing
pull-request-checks.ymlput the "did the docs change?" test in a step-levelif. The job still requested a runner, checked out the repo, and installed tooling before it decided to do nothing.yamllintalso read achart-changedoutput that does not exist, a typo fordocs-changed, so it never linted anything.Fix: move the guard from step level to job level on
markdownlint,yamllint,md-links-lint, andmarkdown-table-formatter-check. Correct thedocs-changedreference. A guarded job now claims no runner at all.4. Required status checks never report on some PRs
Branch protection matches checks by name, and the two ways to skip work do not behave the same:
ifis falseskippedconclusion. Accepted.on.pull_request.pathsdoes not matchThe three
pr-build-*workflows usedpathsfilters that exclude**/*.md. On a docs-only PR all three workflows skip, so these six required contexts never report and the merge stays blocked:A job-level
ifcannot replace thepathsfilter on these jobs, because each one calls a reusable workflow. When the call is skipped, the nested check names never exist. A required check name must therefore be a plain job in a workflow that always runs.Fix: each
pr-build-*workflow now runs on every PR. Achangesjob does the file test, the three build jobs read its output, and a plain aggregator job reports the result.pull-request-checks.ymlgets the same aggregator.5. Artifact names hold a slash, so every PR build fails at once
ARTIFACT_NAME: ${{ github.head_ref }}puts the branch name into the artifact name.actions/upload-artifact@v4rejects a name that contains a forward slash, so a branch such asfix/ci-optimizationsfails the build before it compiles any code:This fault is older than this branch. It also appeared on the run before these commits.
Fix: use
${{ github.run_id }}-${{ github.run_attempt }}, which is always plain digits. The attempt number gives each re-run a new namespace, because an artifact name cannot be reused.ARTIFACT_NAMEonly names and finds artifacts, so layer names and bucket names do not change. The release workflows keepgithub.ref_name, because a tag name has no slash.Action needed after merge
The change adds new check names. It does not remove the old ones. Nothing improves until an admin replaces the required-contexts list on
mainwith these four names:Follow-ups, out of scope here
changesjob matches.github/workflows/*-<lang>.yml. This glob also matchesrelease-build-<lang>.yml, so an edit to a release workflow starts a full PR build. The patterns are unchanged from before to keep this diff small.tj-actions/changed-files@v44is a moving tag. An attacker retargeted that tag in March 2025 to steal secrets. A commit SHA pin removes the risk.Checklist
RENOVATE_APP_IDandRENOVATE_PRIVATE_KEYsecrets exist in this repositoryRenovateBot-SumoLogicis a bypass actor in themainbranch-protection rulemainwith the four names above— written by an agent on behalf of Shubham Gupta