Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Test Self-Referenced Reusable Workflows - #792

Merged
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse
Aug 17, 2026
Merged

Test Self-Referenced Reusable Workflows#792
ptr727 merged 7 commits into
developfrom
feature/dollar-reuse

Conversation

@ptr727

@ptr727ptr727 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What Changed

  • Resolve hub-owned composite actions with GitHub's $/ self-repository syntax.
  • Nest the version and Docker reusable workflows through the same syntax.
  • Remove duplicated Docker orchestration and project-layout defaults.
  • Name the default package actions for the technology they execute.
  • Remove the obsolete Ninja codegen secret.
  • Record the proven self-reference model in the reusable-workflow design and packaged skills.

Why

This draft tests whether a cross-repository reusable workflow can resolve sibling workflows and actions at its own pinned commit. A successful PhotoCleaner run removes the need for extra hub checkouts and synchronized workflow copies.

Validation

  • Docker-based actionlint, with scoped ignores for syntax its current parser does not recognize
  • 686 script unit tests
  • Registry and spec validation
  • Repository pin and line-ending gates
  • Diff-scoped prose checks

PhotoCleaner pull request #58 proves the cross-repository behavior in Actions run 32047594855.

CopilotAI lite review requested due to automatic review settings August 17, 2026 16:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates the hub’s reusable workflows and gates to support GitHub Actions’ $/ self-repository reference syntax, so hub-owned composite actions and sibling reusable workflows can be referenced at the workflow’s pinned commit without additional hub checkouts or duplicated job bodies.

Changes:

  • Allow $/ self-repository refs (and local refs) in the SHA-pinning gate and its unit tests.
  • Switch hub reusable workflows from .hub-checkout-based composite-action resolution to $/ references, and nest release/docker/version workflows via $/.
  • Rename default “package” actions for the technology they run, and remove the obsolete Ninja codegen secret from the codegen task interface.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
scripts/tests/test_repo_gate.pyExtends sha-pin tests to treat $/... as a non-pinnable self-reference.
scripts/repo_gate.pySkips sha-pin checks for $/ refs (self-repo) and updates related documentation.
scripts/README.mdUpdates documented behavior of sha-pin (now also describes self-repo refs).
.github/workflows/validate-task.ymlUses $/ to call the hub default validate action without a .hub checkout fallback.
.github/workflows/run-codegen-pull-request-task.ymlRemoves the optional Ninja API key secret from the workflow_call interface.
.github/workflows/publish-docker-readme-task.ymlUses $/ to run hub default docker-readme transform action without a .hub checkout.
.github/workflows/build-release-task.ymlNests get-version + docker build via $/ reusable workflows; refactors defaults/inputs and validation.
.github/workflows/build-docker-task.ymlUses $/ for the hub default docker-prepare action without a .hub checkout.
.github/actions/pypi-build-default/action.ymlRenames and tightens required inputs (project dir + version file).
.github/actions/nuget-push-default/action.ymlRenames and makes project-file required.
.github/actions/dotnet-publish-default/action.ymlRenames and makes project-file required; updates step naming.
.github/actionlint.yamlAdds scoped ignores for actionlint not recognizing $/ references.
Suppressed comments (1)

scripts/repo_gate.py:266

  • check_sha_pin’s docstring says it checks “uses naming an action”, but the regex scans alluses: (actions and reusable workflows). It also implies every checked SHA “resolves”, but resolution is intentionally limited to refs under the scanned repo’s owner. Updating the docstring would prevent readers from inferring broader guarantees than the function provides.
def check_sha_pin(root: Path, files: list[str]) -> list[str]:
"""Every `uses:` naming an action is a 40-hex SHA, and one under this owner is a SHA that
resolves. A local or self-repository ref names the running commit and is skipped.
Resolution is scoped to the scanned repository's own owner, because that is where the fleet's
own actions live and where the decay this catches comes from: a squash merge deletes the
branch a pin was taken from, and the pin outlives the commit. A third-party action's tag is
stable by comparison, and reading one would make every local run of this gate depend on a
stranger's repository answering. The cost is stated rather than left to be found, and it is

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread.github/workflows/run-codegen-pull-request-task.yml
Comment threadscripts/README.md Outdated
Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 16:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:141

  • The validate-release job enforces project-path inputs purely based on enable_* flags, but the workflow still supports caller-provided build-* hooks. Without checking whether a hook is present, this can force repos that use a custom hook (or any existing callers relying on prior defaults) to supply inputs that may be irrelevant to their hook, and it also makes the new required-by-default contract harder to evolve safely. Consider checking for hook presence (after a checkout) and only requiring these inputs when the hub default will actually run.
 steps:
- name: Validate branch and version consistency step
env:
SEMVER2: ${{ needs.get-version.outputs.SemVer2 }}
BRANCH: ${{ inputs.branch }}

.github/workflows/build-release-task.yml:156

  • The project-input validation should account for whether the caller has provided a build hook. As written, enabling PyPI requires pypi_version_file even when a caller-provided build-pypi hook is used (and that hook path doesn't receive version-file), which can cause unnecessary failures.
 if [[ "$ENABLE_EXECUTABLE" == "true" && -z "$EXECUTABLE_PROJECT" ]]; then
echo "::error::inputs.executable_project is required when inputs.enable_executable is true."
exit 1
fi
if [[ "$ENABLE_NUGET" == "true" && -z "$NUGET_PROJECT" ]]; then

scripts/README.md:85

  • The sha-pin gate checks alluses: references in workflow files (step actions and reusable workflows), not only reusable-workflow calls. The README bullet currently says "every external workflow uses: reference", which could be read as excluding step actions like actions/checkout that are also enforced by this check.
- `sha-pin`: every external workflow `uses:` reference is a 40-hex commit SHA that resolves, with the documented `dotnet/nbgv@master` exception. Local (`./`) and self-repository (`$/`) references run at the workflow commit, so they need no separate pin.

CopilotAI review requested due to automatic review settings August 17, 2026 17:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/build-release-task.yml:163

  • validate-release currently requires inputs.pypi_version_file whenever enable_pypi is true, but that input is only used by the hub default build-pypi implementation (repos with a custom .github/actions/build-pypi hook won’t consume it). This makes pypi_version_file an unconditional contract even when it’s irrelevant to the selected hook path.
 if [[ "$ENABLE_PYPI" == "true" && ( -z "$PYPI_PROJECT_DIR" || -z "$PYPI_VERSION_FILE" ) ]]; then
echo "::error::inputs.pypi_project_dir and inputs.pypi_version_file are required when inputs.enable_pypi is true."
exit 1
fi

.github/workflows/build-release-task.yml:304

  • build-release-task.yml previously had an explicit check that DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN were non-empty before attempting Docker auth. After delegating to build-docker-task.yml, that fast-fail with a targeted error message is gone, and build-docker-task.yml does not currently perform an equivalent non-empty validation before docker/login-action runs. This can make missing-secret failures harder to diagnose.
 build-docker:
name: Build Docker image job
needs: [get-version, validate-release, build-executable, build-nuget, build-pypi]
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
uses: $/.github/workflows/build-docker-task.yml
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:

.github/workflows/build-release-task.yml:290

  • The hub default build-pypi path requires inputs.pypi_version_file, but build-release-task.yml currently only checks it in validate-release (which can’t distinguish between caller hook vs hub default). Add a fast-fail check here scoped to the hub-default path (no .github/actions/build-pypi hook), so custom hooks aren’t forced to provide an unused input.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:
branch: ${{ inputs.branch }}

CopilotAI review requested due to automatic review settings August 17, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

pyproject.toml:15

  • [tool.mypy] exclude is configured as a TOML array, but mypy expects a single regex string. As-is, mypy may ignore the setting or fail to parse it, which would reintroduce the duplicate-module problem this change is trying to avoid.
[tool.mypy]
python_version = "3.13"
files = ["spec", "host-setup", "scripts"]
mypy_path = [".github/actions/prose-gate", ".github/actions/repo-gate"]
exclude = ["scripts/prose_lint.py", "scripts/repo_gate.py"]

scripts/tests/test_repo_gate.py:111

  • This test builds a workflow with a job-level uses: to $/.github/actions/validate-default, but job-level uses: only supports reusable workflows (not composite actions). The repo gate is regex-based so the test still passes, but using syntactically valid YAML here makes the test more representative and easier to reason about.
 def test_a_local_or_self_repository_ref_needs_no_pin(self) -> None:
for ref in (
"./.github/workflows/validate-task.yml",
".github/workflows/validate-task.yml",
"$/.github/workflows/validate-task.yml",
"$/.github/actions/validate-default",
):
with self.subTest(ref=ref):
files = self.workflow(f"jobs:\n a:\n uses: {ref}\n")
self.assertEqual([], repo_gate.check_sha_pin(self.tmp, files))

Comment thread.github/workflows/build-release-task.yml Outdated
CopilotAI review requested due to automatic review settings August 17, 2026 17:43
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Suppressed review findings answered (9 total across four rounds):

  • Round 4952837923, 1 finding:
    • scripts/repo_gate.py:266, "docstring says it checks uses naming an action" - Fixed in ce27556. The canonical docstring now covers every external uses: and states the owner-scoped resolution boundary.
  • Round 4952886439, 3 findings:
    • .github/workflows/build-release-task.yml:141, "enforces project-path inputs purely based on enable flags" - Fixed in ce27556. Requirements moved into the selected hub-default actions, so caller hooks are unconstrained.
    • .github/workflows/build-release-task.yml:156, "enabling PyPI requires pypi_version_file even when a caller-provided hook is used" - Fixed in ce27556 by the same default-action-scoped validation.
    • scripts/README.md:85, "checks all uses references, not only reusable-workflow calls" - Fixed in ce27556. The description now names actions and reusable workflows separately.
  • Round 4953101791, 3 findings:
    • .github/workflows/build-release-task.yml:163, "pypi_version_file is an unconditional contract" - Fixed in ce27556. It is required only by pypi-build-default.
    • .github/workflows/build-release-task.yml:304, "Docker credentials lost the explicit non-empty check" - Fixed in ce27556. The nested Docker task now fails before login with both secret names.
    • .github/workflows/build-release-task.yml:290, "add a fast-fail scoped to the hub-default path" - Fixed in ce27556 inside the default action itself, which is the narrow path that consumes the input.
  • Round 4953141047, 2 findings:
    • pyproject.toml:15, "mypy exclude is configured as a TOML array" - Fixed in 5c88a6d. The two launchers are now selected by one regex string; full uvx mypy@latest passes.
    • scripts/tests/test_repo_gate.py:111, "job-level uses only supports reusable workflows" - Fixed in 5c88a6d. Workflow references remain job-level and the self-action reference is now under a step.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (4)

.github/workflows/build-release-task.yml:232

  • When the caller does not provide a build-nuget hook, the hub default action requires project-file, but this workflow does not validate inputs.nuget_project before invoking the default. Adding an explicit check here makes the failure clearly actionable for downstream callers.
 - name: Run hub build-nuget default step
if: ${{ hashFiles('.github/actions/build-nuget/action.yml') == '' }}
uses: $/.github/actions/nuget-push-default

.github/workflows/build-release-task.yml:270

  • When the caller does not provide a build-pypi hook, the hub default action requires both project-dir and version-file, but this workflow does not validate inputs.pypi_project_dir / inputs.pypi_version_file before invoking the default. Adding an explicit check here makes missing/empty inputs fail with a workflow-level message that points to the right with: fields.
 - name: Run hub build-pypi default step
if: ${{ hashFiles('.github/actions/build-pypi/action.yml') == '' }}
uses: $/.github/actions/pypi-build-default
with:

docs/reusable-workflows.md:185

  • The doc says build-release-task.yml "validates those inputs" (explicit project paths) when targets are enabled, but the current implementation relies on the called default actions to fail when paths are empty (e.g., dotnet-publish-default requires project-file). This is a documentation mismatch that can mislead downstream adopters about where validation occurs.
`build-release-task.yml` reaches `get-version-task.yml` and `build-docker-task.yml` through `$/`, so both sibling tasks resolve at the same hub commit the downstream caller pins. It keeps `validate-release` inline because that gate belongs to the release orchestrator. `build-docker-task.yml` also ships as a task in its own right for a caller that wants only the Docker leg. The `dotnet-publish-default`, `nuget-push-default`, and `pypi-build-default` actions require explicit project paths. `build-release-task.yml` validates those inputs when their targets are enabled and forwards them to the matching default.

.github/workflows/build-release-task.yml:189

  • When the caller does not provide a build-executable hook, the hub default action requires project-file, but this workflow does not validate inputs.executable_project before invoking the default. The resulting failure message comes from the action and doesn’t clearly point back to the workflow input that needs to be set.

This issue also appears in the following locations of the same file:

  • line 230
  • line 267
 - name: Run hub build-executable default step
if: ${{ hashFiles('.github/actions/build-executable/action.yml') == '' }}
uses: $/.github/actions/dotnet-publish-default

CopilotAI review requested due to automatic review settings August 17, 2026 17:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 17, 2026 17:58
@ptr727
ptr727 merged commit 4761973 into developAug 17, 2026
8 checks passed
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Late suppressed findings from review 4953201774, which arrived after the earlier consolidated disposition:

  • .github/workflows/build-release-task.yml:189, .github/workflows/build-release-task.yml:232, and .github/workflows/build-release-task.yml:270, requests to duplicate default-action input checks in the orchestrating workflow: Declined. Each validation belongs to the default action that consumes the input and runs only when that default is selected. The actions emit explicit errors for project-file, project-dir, and version-file. Duplicating those contracts in the workflow would create two validation sources while caller-provided hooks intentionally remain unconstrained.
  • docs/reusable-workflows.md:185, incorrect claim that build-release-task.yml performs those checks: Fixed in Clarify Default Action Validation #795. The guide states that each selected default validates its own inputs and that caller-provided hooks may use different inputs.

All four suppressed findings now have an explicit disposition.

ptr727 added a commit that referenced this pull request Aug 17, 2026
## Summary
Correct the reusable-workflow guide's description of default-action
input validation.
## Why
The late suppressed review on #792 correctly identified that the guide
assigned validation to `build-release-task.yml`. Each selected hub
default action performs that validation instead. Caller-provided hooks
remain free to use different inputs.
## Validation
- Diff-scoped prose lint
- markdownlint, 120 files
- Ruff lint and format checks
- mypy
- Repository gate
- EditorConfig checker
- `git diff --check`
Sign up for freeto 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

@ptr727