Skip to content

Reference the pipelines absolutely, not relatively - #22

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/dependabot-ci-workflow-rollout-fbrhdn
Sep 16, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
claude/dependabot-ci-workflow-rollout-fbrhdn

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Urgent — ktsu-dev/Sorting's main currently has no working CI

The first push to main after Sorting adopted ci.yml failed to compile:

Invalid workflow file

error parsing called workflow ".github/workflows/ci.yml"
 -> "ktsu-dev/.github/.github/workflows/ci-shared.yml@release" (source tag with sha:af44498387b3311c24e3f9352575307a8e51ef6c)
 --> "./.github/workflows/dotnet.yml" : workflow was not found.

af44498 is the annotated tag's own object sha, not c9ef0b3 which it points at. A relative ./ inside a workflow that was itself reached through a tag is resolved by GitHub against the tag object, and a tag object has no tree — so the lookup finds nothing.

Correcting the record

I reported the nested relative resolution as verified. That was wrong, and the way it was wrong is the interesting part.

The canary's pull_request run genuinely did resolve it — the run recorded ktsu-dev/.github/.github/workflows/dotnet.yml@af44498 in referenced_workflows and went green across all eight jobs, three platforms, Sonar and all. I treated that as proof the nested case worked.

It holds on pull_request and fails on push. The evidence was real; the conclusion I drew from it was too broad. A construct that works right up until the first push to a default branch is worse than one that never works at all, because it passes the canary.

The fix

Both pipeline references in ci-shared.yml become absolute:

-    uses: ./.github/workflows/dotnet.yml
+    uses: ktsu-dev/.github/.github/workflows/dotnet.yml@release

Naming the repository and tag explicitly resolves identically on every event, and works whether or not the tag is annotated. Because release is promoted as one unit, the dispatcher and the pipeline it selects still move together — the atomicity the relative form was chosen for is preserved.

The cost, recorded in the docs

A pull request against this repository now tests its ci-shared.yml against the released pipelines rather than its own. Changing a pipeline and the dispatcher together therefore wants two promotions, or a throwaway tag. That is a real downgrade in testability and it is written down in docs/shared-ci.md rather than left to be rediscovered.

After this merges

  1. Dispatch Promote release (ref main).
  2. Re-run Sorting's failed main run — it should compile and go green, this time exercising Release and Security Scanning, which the PR run skipped by design and which have therefore never run through the dispatcher.

Bearing on the fan-out

The fan-out stays blocked until Sorting's main is green. This failure mode is invisible on a pull request, so "the canary PR passed" is not sufficient evidence to migrate 50 repositories — the canary's main has to be green too.

Testing

actionlint 1.7.7 with shellcheck clean; markdownlint-cli clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_014RABe2NufFc9hwm94iB3Rf


Generated by Claude Code

Sorting's first push to main after adopting ci.yml failed to compile:

  error parsing called workflow ".github/workflows/ci.yml"
   -> "ktsu-dev/.github/.github/workflows/ci-shared.yml@release" (source tag with sha:af44498...)
   --> "./.github/workflows/dotnet.yml" : workflow was not found.

af44498 is the annotated tag's own object sha, not c9ef0b3 which it points
at. A relative `./` inside a workflow reached through a tag is resolved
against the tag object, and a tag object has no tree, so nothing is found.

This is worth stating precisely because the relative form DID resolve on the
canary's pull_request run -- the run recorded dotnet.yml@af44498 and went green
across all eight jobs -- and I took that as proof the nested case worked. It
holds on pull_request and fails on push, so the evidence was real and the
conclusion drawn from it was wrong. A form that works until the first push to a
default branch is worse than one that never works.

Naming the repository and tag explicitly resolves identically on every event.
`release` is promoted as one unit, so the dispatcher and the pipeline it selects
still move together.

The cost is that a pull request here tests its ci-shared.yml against the
released pipelines rather than its own, so changing a pipeline and the
dispatcher together wants two promotions. Recorded in the docs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RABe2NufFc9hwm94iB3Rf
@matt-edmondson
matt-edmondson merged commit 80a0b3b into main Sep 16, 2026
3 checks passed
@matt-edmondson
matt-edmondson deleted the claude/dependabot-ci-workflow-rollout-fbrhdn branch September 16, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants