Use self-repository syntax for composite actions - #63
Conversation
GitHub's new self-repository syntax resolves a `uses:` value to the running repository at the running commit, with no checkout. That is exactly the guarantee the reusable workflows were hand-rolling, and it lifts the restriction that kept the composite actions from installing the CLI for themselves. Reusable workflows: drop the nested `actions/checkout` of this repo into `.odp-releaser/` from notify, bump-images and report-merged, and address the actions as `$/.github/actions/...`. bump-images also loses the step that wrote `/.odp-releaser/` into `.git/info/exclude` — with nothing of this repo in the workspace, the bump's `git add -A` and create-pull-request have nothing extra to pick up. report-merged now checks out nothing at all. Composite actions: bump_images, report_deployment and comment_on_pr each run `uses: $/.github/actions/install` as their first step, so callers no longer need a separate install step. This was previously impossible — relative `uses:` paths resolve against the workflow's workspace rather than the action's repo (actions/runner#1348) — and the headers and docs that cited that limitation are updated. install gains a PATH check so it is a no-op when the CLI is already present, which also skips setup-uv. That keeps a caller who still runs it explicitly (as the reusable workflows do, for the precise cache key) from doing the work twice. First install wins, so pin install and its sibling to the same ref. Add e2e-action-self-install to CI: the reusable workflows always install first, so they only exercise the no-op branch. That job calls bump_images alone, with no install step and no uv on the PATH, so the self-install path has to actually work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fZrq3juSRFpWyYhHuVVtN
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #63 +/- ##
=======================================
Coverage 98.41% 98.41%
=======================================
Files 41 41
Lines 2141 2141
=======================================
Hits 2107 2107
Misses 34 34 ☔ View full report in Codecov by Harness. |
abkfenris
left a comment
There was a problem hiding this comment.
Tighten up a lot of the descriptions
| # `$/` resolves to this repo at the commit this action is running from, | ||
| # so the CLI stays in lockstep with the ref the caller pinned. A no-op | ||
| # when the caller already installed it. | ||
| uses: $/.github/actions/install |
There was a problem hiding this comment.
| # `$/` resolves to this repo at the commit this action is running from, | |
| # so the CLI stays in lockstep with the ref the caller pinned. A no-op | |
| # when the caller already installed it. | |
| uses: $/.github/actions/install | |
| uses: $/.github/actions/install |
Unnecessarily verbose.
| # Inlined here rather than in a sibling `sync_image` action because the | ||
| # ordering above is the whole point. |
There was a problem hiding this comment.
| # Inlined here rather than in a sibling `sync_image` action because the | |
| # ordering above is the whole point. |
| # `$/` resolves to this repo at the commit this action is running from, | ||
| # so the CLI stays in lockstep with the ref the caller pinned. A no-op | ||
| # when the caller already installed it. | ||
| uses: $/.github/actions/install |
There was a problem hiding this comment.
| # `$/` resolves to this repo at the commit this action is running from, | |
| # so the CLI stays in lockstep with the ref the caller pinned. A no-op | |
| # when the caller already installed it. | |
| uses: $/.github/actions/install | |
| uses: $/.github/actions/install |
| - name: Install ODP Releaser | ||
| # `$/` resolves to this repo at the commit this action is running from, | ||
| # so the CLI stays in lockstep with the ref the caller pinned. A no-op | ||
| # when the caller already installed it. | ||
| uses: $/.github/actions/install | ||
| with: |
There was a problem hiding this comment.
| - name: Install ODP Releaser | |
| # `$/` resolves to this repo at the commit this action is running from, | |
| # so the CLI stays in lockstep with the ref the caller pinned. A no-op | |
| # when the caller already installed it. | |
| uses: $/.github/actions/install | |
| with: | |
| - name: Install ODP Releaser | |
| uses: $/.github/actions/install | |
| with: |
| # `$/` resolves to this workflow's own repo at the same commit GitHub | ||
| # resolved for this workflow file, so the composite actions below (and | ||
| # the CLI they install) stay in lockstep with the caller's pinned | ||
| # workflow ref. Nothing of this repo lands in the workspace, so the | ||
| # bump_images action's `git add -A` and peter-evans/create-pull-request | ||
| # (which commits untracked files) have nothing extra to trip over. |
There was a problem hiding this comment.
| # `$/` resolves to this workflow's own repo at the same commit GitHub | |
| # resolved for this workflow file, so the composite actions below (and | |
| # the CLI they install) stay in lockstep with the caller's pinned | |
| # workflow ref. Nothing of this repo lands in the workspace, so the | |
| # bump_images action's `git add -A` and peter-evans/create-pull-request | |
| # (which commits untracked files) have nothing extra to trip over. |
| # `$/` resolves to this workflow's own repo at the same commit GitHub | ||
| # resolved for this workflow file, so the action (and the CLI it | ||
| # installs) stays in lockstep with the caller's pinned workflow ref, | ||
| # with no checkout of this repo needed. |
There was a problem hiding this comment.
| # `$/` resolves to this workflow's own repo at the same commit GitHub | |
| # resolved for this workflow file, so the action (and the CLI it | |
| # installs) stays in lockstep with the caller's pinned workflow ref, | |
| # with no checkout of this repo needed. |
| # `$/` resolves to this workflow's own repo at the same commit GitHub | ||
| # resolved for this workflow file, so the composite actions below (and | ||
| # the CLI they install) stay in lockstep with the caller's pinned | ||
| # workflow ref. Nothing is checked out at all: this repo needs no | ||
| # checkout under `$/`, and the deploy repo never did — everything | ||
| # needed travels in the PR body. |
There was a problem hiding this comment.
| # `$/` resolves to this workflow's own repo at the same commit GitHub | |
| # resolved for this workflow file, so the composite actions below (and | |
| # the CLI they install) stay in lockstep with the caller's pinned | |
| # workflow ref. Nothing is checked out at all: this repo needs no | |
| # checkout under `$/`, and the deploy repo never did — everything | |
| # needed travels in the PR body. |
| They do it by referencing the sibling `install` action with GitHub's | ||
| [self-repository syntax](https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/) | ||
| (`uses: $/.github/actions/install`), which resolves to this repo at the exact | ||
| commit the outer action is running from. That keeps the action and the CLI it | ||
| runs in lockstep with whatever ref you pinned, and it is how the reusable | ||
| workflows reach these same actions internally. |
There was a problem hiding this comment.
| They do it by referencing the sibling `install` action with GitHub's | |
| [self-repository syntax](https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/) | |
| (`uses: $/.github/actions/install`), which resolves to this repo at the exact | |
| commit the outer action is running from. That keeps the action and the CLI it | |
| runs in lockstep with whatever ref you pinned, and it is how the reusable | |
| workflows reach these same actions internally. | |
| They do it by referencing the sibling `install` action with GitHub's | |
| [self-repository syntax](https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/) | |
| (`uses: $/.github/actions/install`), which resolves to this repo at the same | |
| commit the outer action is running from. |
| `bump_images`, `report_deployment` and `comment_on_pr` each install the | ||
| `odp-releaser` CLI for themselves, so **one step is all you need** — there is | ||
| no separate install step to remember. |
There was a problem hiding this comment.
| `bump_images`, `report_deployment` and `comment_on_pr` each install the | |
| `odp-releaser` CLI for themselves, so **one step is all you need** — there is | |
| no separate install step to remember. | |
| `bump_images`, `report_deployment` and `comment_on_pr` each install the | |
| `odp-releaser` CLI. |
| commit GitHub resolved for the workflow file in this run. The actions install | ||
| the `odp-releaser` CLI from that same commit, so the workflow YAML, the | ||
| actions, and the CLI they invoke stay in lockstep with the ref you pinned — | ||
| and no checkout of this repository is involved. |
There was a problem hiding this comment.
| commit GitHub resolved for the workflow file in this run. The actions install | |
| the `odp-releaser` CLI from that same commit, so the workflow YAML, the | |
| actions, and the CLI they invoke stay in lockstep with the ref you pinned — | |
| and no checkout of this repository is involved. | |
| commit GitHub resolved for the workflow file in this run. The actions install | |
| the `odp-releaser` CLI from that same commit. |
CI shows github.action_ref resolves to the running commit under a self-repository reference rather than to an empty string, so drop the claim that it is empty and just point at setting the suffix explicitly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fZrq3juSRFpWyYhHuVVtN
Address review on #63: the self-repository syntax is explained once in the docs, so repeating it above every install step was noise. Drops the per-call-site comments in the three composite actions and three reusable workflows, the stale sync_image aside in bump_images (the ordering rationale directly above it already carries the point), and the trailing restatements in docs/api/actions.md and docs/getting-started.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fZrq3juSRFpWyYhHuVVtN
The change should be shrinking these files, not shuffling comments around. Removes the per-action "CLI not found on the PATH; run install first" guards, which cannot fire now that each action installs the CLI in its immediately preceding step, and the thrice-repeated header paragraph saying so. Condenses what was left: install's header and check-step comment, the e2e job comment, and the docs, which explained the self-repository syntax in two places and the install behavior in three. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fZrq3juSRFpWyYhHuVVtN
Summary
Refactor composite actions and reusable workflows to use GitHub's self-repository syntax (
$/) instead of explicit checkouts. This simplifies the workflow structure, eliminates unnecessary repository checkouts, and makes the actions self-contained by having them install the CLI for themselves.Key Changes
Composite actions now self-install:
bump_images,report_deployment, andcomment_on_preach call theinstallaction for themselves using$/.github/actions/install, eliminating the need for callers to remember a separate install step.Reusable workflows simplified: Removed explicit checkouts of the odp-releaser repository at
job.workflow_shafrombump-images.yml,report-merged.yml, andnotify.yml. These workflows now reference composite actions directly using$/.github/actions/...syntax, which automatically resolves to the correct commit.Install action enhanced: Added a check to detect if
odp-releaseris already on the PATH, making the action a no-op when the CLI is already installed. This allows the action to compose safely with itself when both explicit and implicit installs occur.Documentation updated: Clarified that the three main composite actions install the CLI themselves, making the
installaction optional for most use cases. Updated examples to remove the separate install step and explained the self-repository syntax and its benefits.E2E test coverage added: New
e2e-action-self-installjob validates thatbump_imagescan install the CLI for itself when called without a prior install step and without uv on the PATH.Implementation Details
The
$/.github/actions/installsyntax resolves to the action's own repository at the exact commit the outer action is running from, keeping the action and CLI in lockstep with the caller's pinned ref.The install action's no-op behavior when the CLI already exists prevents redundant work and allows safe composition of multiple install calls within a single job.
Cache suffixes are now explicitly passed when using
$/references (which have emptygithub.action_ref) to maintain proper cache keying.Error messages in composite actions were updated to guide users to check the install step's log rather than asking them to run a separate install action.
https://claude.ai/code/session_016fZrq3juSRFpWyYhHuVVtN