From 72048c83f3285418909d9017a6a98ae5d478023a Mon Sep 17 00:00:00 2001 From: Charles Green Date: Fri, 31 Jul 2026 10:09:57 +0900 Subject: [PATCH] fix: repair the workflow v0.1.7 could not load, and move to client-id The v0.1.7 reusable workflow does not run. The comment dispatch fix added a second `env:` block to the run step rather than adding to the first one. Duplicate keys are legal to yaml.safe_load, which keeps the last, so GH_TOKEN and both Azure variables were discarded. GitHub is stricter and refuses to load the file, so every run since that merge failed in about a second having started no job at all. The gate could not see it. It parsed workflows with yaml.safe_load, which is precisely the parser that accepts the file. It now rejects a duplicate key anywhere in a workflow, a template, or the embedded caller, and the check was written against the real v0.1.7 file to confirm it fails on it. Closes the deprecation warning at the same time, since it touches the same steps. `create-github-app-token` resolves `client-id || app-id` into a single value and passes it straight to createAppAuth, so the inputs are interchangeable in practice at v3.2.0 even though they are not in principle. Callers passing `github-app-id` keep working; the documented path is now SIMPLYCUBED_GH_APP_CLIENT_ID. Closes #93 --- .github/workflows/simplycubed-caller.yml | 6 ++-- .github/workflows/simplycubed.yml | 23 +++++++----- .github/workflows/tag-release.yml | 2 +- CHANGELOG.md | 19 ++++++++++ README.md | 8 ++--- STATUS.md | 8 +++-- cmd/simplycubed/main.go | 4 +-- cmd/simplycubed/main_test.go | 4 +-- cmd/simplycubed/simplycubed-caller.yml.tmpl | 6 ++-- cmd/simplycubed/simplycubed-selftest.yml.tmpl | 2 +- docs/setup.md | 9 ++--- docs/templates/simplycubed-caller.yml | 12 +++---- docs/templates/simplycubed-selftest.yml | 2 +- docs/troubleshooting.md | 3 +- scripts/check-workflows.sh | 35 +++++++++++++++++-- 15 files changed, 103 insertions(+), 40 deletions(-) diff --git a/.github/workflows/simplycubed-caller.yml b/.github/workflows/simplycubed-caller.yml index e3f5fdf..689dfa4 100644 --- a/.github/workflows/simplycubed-caller.yml +++ b/.github/workflows/simplycubed-caller.yml @@ -24,7 +24,7 @@ jobs: uses: simplycubed/code/.github/workflows/simplycubed.yml@main with: ref: ${{ github.event.issue.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} issue-number: ${{ github.event.issue.number }} actor-login: ${{ github.event.sender.login }} azure-openai-endpoint: ${{ vars.AZURE_OPENAI_ENDPOINT }} @@ -41,7 +41,7 @@ jobs: uses: simplycubed/code/.github/workflows/simplycubed.yml@main with: ref: ${{ github.event.pull_request.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} pr-number: ${{ github.event.pull_request.number }} actor-login: ${{ github.event.review.user.login }} azure-openai-endpoint: ${{ vars.AZURE_OPENAI_ENDPOINT }} @@ -65,7 +65,7 @@ jobs: uses: simplycubed/code/.github/workflows/simplycubed.yml@main with: ref: ${{ github.event.issue.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} comment-body: ${{ github.event.comment.body }} issue-number: ${{ github.event.issue.pull_request == null && github.event.issue.number || '' }} pr-number: ${{ github.event.issue.pull_request != null && github.event.issue.number || '' }} diff --git a/.github/workflows/simplycubed.yml b/.github/workflows/simplycubed.yml index 28a2f6c..ad5452c 100644 --- a/.github/workflows/simplycubed.yml +++ b/.github/workflows/simplycubed.yml @@ -7,9 +7,17 @@ on: description: Issue or pull request number, used for concurrency. required: true type: string + github-app-client-id: + description: GitHub App Client ID for the SimplyCubed App, the Iv23 string + on the App settings page. + default: "" + required: false + type: string github-app-id: - description: GitHub App ID for the SimplyCubed App. - required: true + description: Deprecated, kept so an existing caller keeps working. Pass + github-app-client-id instead. + default: "" + required: false type: string issue-number: description: Issue number to run, when triggered from issues:labeled. @@ -46,7 +54,7 @@ on: type: string version: description: SimplyCubed CLI tag to install. - default: v0.1.7 + default: v0.1.8 required: false type: string secrets: @@ -72,7 +80,7 @@ jobs: id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: - app-id: ${{ inputs['github-app-id'] }} + client-id: ${{ inputs['github-app-client-id'] || inputs['github-app-id'] }} private-key: ${{ secrets['github-app-private-key'] }} owner: ${{ steps.repo.outputs.owner }} repositories: ${{ steps.repo.outputs.name }} @@ -108,12 +116,12 @@ jobs: GH_TOKEN: ${{ steps.app-token.outputs.token }} AZURE_OPENAI_ENDPOINT: ${{ inputs['azure-openai-endpoint'] }} AZURE_OPENAI_API_KEY: ${{ secrets['azure-openai-api-key'] }} + COMMENT_BODY: ${{ inputs['comment-body'] }} # --base is explicit because actions/checkout never creates origin/HEAD, # which is the CLI's default base. The CLI resolves that case on its own # now, but naming the branch the event came from is exact rather than # inferred. - env: - COMMENT_BODY: ${{ inputs['comment-body'] }} + # # A comment goes through the parser, which recognises a fixed vocabulary # and does nothing otherwise. Without this every comment beginning with # the mention would start a full run, including "help" and including a @@ -141,7 +149,7 @@ jobs: id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: - app-id: ${{ inputs['github-app-id'] }} + client-id: ${{ inputs['github-app-client-id'] || inputs['github-app-id'] }} private-key: ${{ secrets['github-app-private-key'] }} owner: ${{ steps.repo.outputs.owner }} repositories: ${{ steps.repo.outputs.name }} @@ -177,7 +185,6 @@ jobs: GH_TOKEN: ${{ steps.app-token.outputs.token }} AZURE_OPENAI_ENDPOINT: ${{ inputs['azure-openai-endpoint'] }} AZURE_OPENAI_API_KEY: ${{ secrets['azure-openai-api-key'] }} - env: COMMENT_BODY: ${{ inputs['comment-body'] }} run: | if [ -n "${COMMENT_BODY}" ]; then diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml index 3be039a..273c1f1 100644 --- a/.github/workflows/tag-release.yml +++ b/.github/workflows/tag-release.yml @@ -33,7 +33,7 @@ jobs: id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: - app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} private-key: ${{ secrets.SIMPLYCUBED_GH_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: ${{ github.event.repository.name }} diff --git a/CHANGELOG.md b/CHANGELOG.md index ced0e91..88cbb0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes are recorded here and summarized again in the matching GitHub release notes for each tag. +## v0.1.8 + +- **The Actions runtime was dead in `v0.1.7` and is fixed here.** The comment + dispatch fix gave the run step a second `env:` block instead of adding to the + first. YAML keeps the last of two identical keys, so `GH_TOKEN` and both Azure + variables were dropped, and GitHub, which is stricter than the parser the gate + used, refused to load the file at all. Every run since that merge failed in + about a second without starting a job. Upgrade from `v0.1.7`. +- The gate now rejects a duplicate YAML key anywhere in a workflow, template, or + the embedded caller. `yaml.safe_load` accepted the broken file and kept the + last key, which is exactly why the break reached a release: green gate, dead + workflow. This is the second time a workflow defect passed a gate that only + compiled Go, and the check is written to fail on the real file from `v0.1.7`. +- The App token step now uses `client-id`, which ends the deprecation warning + on every run. The two inputs are not interchangeable in principle, but the + action resolves `client-id || app-id` into one value, so adopters passing + `github-app-id` keep working while the documented path moves to + `SIMPLYCUBED_GH_APP_CLIENT_ID`. + ## v0.1.7 - Fixed comment commands. The reusable workflow declared `comment-body` and never diff --git a/README.md b/README.md index c639a1e..47c8d18 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An autonomous coding agent that lives inside your own GitHub. You file an issue, it opens a pull request, and a human decides whether to merge. -> Beta, at `v0.1.7`. Product overview: [simplycubed.com/code](https://simplycubed.com/code?utm_source=github&utm_medium=readme&utm_campaign=code). See [Status](#status). +> Beta, at `v0.1.8`. Product overview: [simplycubed.com/code](https://simplycubed.com/code?utm_source=github&utm_medium=readme&utm_campaign=code). See [Status](#status). ### Try it without letting it write anything @@ -115,7 +115,7 @@ Start with the adopter quickstart in [docs/setup.md](docs/setup.md). It covers t Install the pinned release you want to run: ```sh -go install github.com/simplycubed/code/cmd/simplycubed@v0.1.7 +go install github.com/simplycubed/code/cmd/simplycubed@v0.1.8 simplycubed version ``` @@ -140,7 +140,7 @@ To run the loop inside your own GitHub Actions: Install it on the repo. 2. In the adopter repo, run `simplycubed init --workflow`. That writes `.github/simplycubed.yml`, writes `.github/workflows/simplycubed.yml` pinned to a released reusable-workflow tag, and creates the `sc:*` labels through your local `gh` auth. 3. Fill in the real `gate:` in `.github/simplycubed.yml`. -4. Add repository variable `SIMPLYCUBED_GH_APP_ID`, repository secret `SIMPLYCUBED_GH_APP_PRIVATE_KEY`, repository variable `AZURE_OPENAI_ENDPOINT`, and repository secret `AZURE_OPENAI_API_KEY`. +4. Add repository variable `SIMPLYCUBED_GH_APP_CLIENT_ID` (the App Client ID, the `Iv23` string on the App settings page), repository secret `SIMPLYCUBED_GH_APP_PRIVATE_KEY`, repository variable `AZURE_OPENAI_ENDPOINT`, and repository secret `AZURE_OPENAI_API_KEY`. These are per-repository and are never inherited from SimplyCubed: a reusable workflow runs with the calling repository's own variables and secrets, so you bring your own Azure endpoint and key, and pay for your own tokens. The private key secret must be the full PEM contents, including the `-----BEGIN` and `-----END` lines. 5. Open a setup pull request in the adopter repo and merge it yourself. Setup files are written locally by `simplycubed init` and merged by a human, because the runtime holds no `workflows` permission and cannot add its own workflow files. @@ -210,7 +210,7 @@ The first engine adapter targets the Codex CLI running against Azure OpenAI. Tod ## Status -Beta, and honest about it. Two loops run end to end via the CLI on the Codex-on-Azure engine: issue to pull request, and fix-on-request (a human requests changes, the fixer addresses them and pushes back). `v0.1.7` is the latest release and you should still expect rough edges. +Beta, and honest about it. Two loops run end to end via the CLI on the Codex-on-Azure engine: issue to pull request, and fix-on-request (a human requests changes, the fixer addresses them and pushes back). `v0.1.8` is the latest release and you should still expect rough edges. Roadmap, roughly in order: diff --git a/STATUS.md b/STATUS.md index 3677b34..a0a7d27 100644 --- a/STATUS.md +++ b/STATUS.md @@ -27,10 +27,14 @@ The Actions runtime authenticates as the `simplycubed-code[bot]` GitHub App. Each job mints its own installation token scoped to one repository with `contents`, `issues`, and `pull-requests` permissions only. -`v0.1.6` is the current release. `go install -github.com/simplycubed/code/cmd/simplycubed@v0.1.6` works today. `v0.1.2` and `v0.1.4` are retracted in `go.mod` because those tags pointed at the wrong +`v0.1.8` is the current release. `go install +github.com/simplycubed/code/cmd/simplycubed@v0.1.8` works today. `v0.1.2` and `v0.1.4` are retracted in `go.mod` because those tags pointed at the wrong commits. +Do not use `v0.1.7`. Its copy of the reusable workflow has a duplicate `env:` +key, which GitHub refuses to load, so every run under it fails in about a second +without starting a job. `v0.1.8` is the fix. + Both loops were dogfooded: the issue-to-PR loop produced the merged dependency-upgrade PR on `charlesgreen/gsm`. diff --git a/cmd/simplycubed/main.go b/cmd/simplycubed/main.go index 1fdbc81..52711f4 100644 --- a/cmd/simplycubed/main.go +++ b/cmd/simplycubed/main.go @@ -131,7 +131,7 @@ gate: ` const ( - latestKnownWorkflowTag = "v0.1.7" + latestKnownWorkflowTag = "v0.1.8" callerWorkflowTagToken = "__SIMPLYCUBED_TAG__" simplycubedAppLogin = "simplycubed-code[bot]" ) @@ -531,7 +531,7 @@ func initCmd(argv []string, stdout io.Writer) error { fmt.Fprintln(stdout, " - disable the App webhook, set install visibility to Any account, and install it on the repo") fmt.Fprintln(stdout, " - write the real gate in .github/simplycubed.yml") fmt.Fprintln(stdout, " - verify that gate is green on your main branch") - fmt.Fprintln(stdout, " - set the SIMPLYCUBED_GH_APP_ID repo variable") + fmt.Fprintln(stdout, " - set the SIMPLYCUBED_GH_APP_CLIENT_ID repo variable to the App Client ID, the Iv23 string on the App settings page") fmt.Fprintln(stdout, " - add the SIMPLYCUBED_GH_APP_PRIVATE_KEY repo secret with the full PEM, including BEGIN/END lines") fmt.Fprintln(stdout, " - set the AZURE_OPENAI_ENDPOINT repo variable") fmt.Fprintln(stdout, " - add the AZURE_OPENAI_API_KEY repo secret") diff --git a/cmd/simplycubed/main_test.go b/cmd/simplycubed/main_test.go index e0113f3..cb49a83 100644 --- a/cmd/simplycubed/main_test.go +++ b/cmd/simplycubed/main_test.go @@ -128,7 +128,7 @@ exit 0 "disable the App webhook, set install visibility to Any account, and install it on the repo", "write the real gate in .github/simplycubed.yml", "verify that gate is green on your main branch", - "set the SIMPLYCUBED_GH_APP_ID repo variable", + "set the SIMPLYCUBED_GH_APP_CLIENT_ID repo variable to the App Client ID", "add the SIMPLYCUBED_GH_APP_PRIVATE_KEY repo secret with the full PEM, including BEGIN/END lines", "set the AZURE_OPENAI_ENDPOINT repo variable", "add the AZURE_OPENAI_API_KEY repo secret", @@ -242,7 +242,7 @@ exit 0 } for _, want := range []string{ "uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.0", - "github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }}", + "github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }}", "azure-openai-api-key: ${{ secrets.AZURE_OPENAI_API_KEY }}", "github-app-private-key: ${{ secrets.SIMPLYCUBED_GH_APP_PRIVATE_KEY }}", } { diff --git a/cmd/simplycubed/simplycubed-caller.yml.tmpl b/cmd/simplycubed/simplycubed-caller.yml.tmpl index cdb6224..81e78b4 100644 --- a/cmd/simplycubed/simplycubed-caller.yml.tmpl +++ b/cmd/simplycubed/simplycubed-caller.yml.tmpl @@ -14,7 +14,7 @@ jobs: uses: simplycubed/code/.github/workflows/simplycubed.yml@__SIMPLYCUBED_TAG__ with: ref: ${{ github.event.issue.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} issue-number: ${{ github.event.issue.number }} actor-login: ${{ github.event.sender.login }} azure-openai-endpoint: ${{ vars.AZURE_OPENAI_ENDPOINT }} @@ -30,7 +30,7 @@ jobs: uses: simplycubed/code/.github/workflows/simplycubed.yml@__SIMPLYCUBED_TAG__ with: ref: ${{ github.event.pull_request.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} pr-number: ${{ github.event.pull_request.number }} actor-login: ${{ github.event.review.user.login }} azure-openai-endpoint: ${{ vars.AZURE_OPENAI_ENDPOINT }} @@ -53,7 +53,7 @@ jobs: uses: simplycubed/code/.github/workflows/simplycubed.yml@__SIMPLYCUBED_TAG__ with: ref: ${{ github.event.issue.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} comment-body: ${{ github.event.comment.body }} issue-number: ${{ github.event.issue.pull_request == null && github.event.issue.number || '' }} pr-number: ${{ github.event.issue.pull_request != null && github.event.issue.number || '' }} diff --git a/cmd/simplycubed/simplycubed-selftest.yml.tmpl b/cmd/simplycubed/simplycubed-selftest.yml.tmpl index 5ce466a..eaff259 100644 --- a/cmd/simplycubed/simplycubed-selftest.yml.tmpl +++ b/cmd/simplycubed/simplycubed-selftest.yml.tmpl @@ -34,7 +34,7 @@ jobs: id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: - app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} private-key: ${{ secrets.SIMPLYCUBED_GH_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: ${{ github.event.repository.name }} diff --git a/docs/setup.md b/docs/setup.md index 40681cd..3c3e235 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -16,7 +16,7 @@ Prerequisites: 1. Install the CLI: ```sh -go install github.com/simplycubed/code/cmd/simplycubed@v0.1.7 +go install github.com/simplycubed/code/cmd/simplycubed@v0.1.8 simplycubed version ``` @@ -56,7 +56,7 @@ simplycubed run owner/repo#N --repo-dir . 4. In the GitHub repository settings, add: -- Variable: `SIMPLYCUBED_GH_APP_ID` +- Variable: `SIMPLYCUBED_GH_APP_CLIENT_ID`, the App Client ID, the `Iv23` string on the App settings page - Secret: `SIMPLYCUBED_GH_APP_PRIVATE_KEY` - Variable: `AZURE_OPENAI_ENDPOINT` - Secret: `AZURE_OPENAI_API_KEY` @@ -119,7 +119,7 @@ flowchart TB end subgraph actions["GitHub Actions: the App is the identity"] - A1["repository variables
AZURE_OPENAI_ENDPOINT
SIMPLYCUBED_GH_APP_ID"] + A1["repository variables
AZURE_OPENAI_ENDPOINT
SIMPLYCUBED_GH_APP_CLIENT_ID"] A2["repository secrets
AZURE_OPENAI_API_KEY
SIMPLYCUBED_GH_APP_PRIVATE_KEY"] A3["per-job installation token
contents, issues, pull requests"] A4["simplycubed run / address"] @@ -191,7 +191,8 @@ passes: `azure-openai-endpoint`. - `secrets.AZURE_OPENAI_API_KEY` to the reusable workflow secret `azure-openai-api-key`. -- `vars.SIMPLYCUBED_GH_APP_ID` to the reusable workflow input `github-app-id`. +- `vars.SIMPLYCUBED_GH_APP_CLIENT_ID` to the reusable workflow input + `github-app-client-id`. - `secrets.SIMPLYCUBED_GH_APP_PRIVATE_KEY` to the reusable workflow secret `github-app-private-key`. diff --git a/docs/templates/simplycubed-caller.yml b/docs/templates/simplycubed-caller.yml index cb291e3..133f469 100644 --- a/docs/templates/simplycubed-caller.yml +++ b/docs/templates/simplycubed-caller.yml @@ -11,10 +11,10 @@ on: jobs: run: if: ${{ github.event_name == 'issues' && github.event.label.name == 'sc:go' }} - uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.7 + uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.8 with: ref: ${{ github.event.issue.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} issue-number: ${{ github.event.issue.number }} actor-login: ${{ github.event.sender.login }} azure-openai-endpoint: ${{ vars.AZURE_OPENAI_ENDPOINT }} @@ -27,10 +27,10 @@ jobs: if: >- github.event_name == 'pull_request_review' && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.review.author_association) - uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.7 + uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.8 with: ref: ${{ github.event.pull_request.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} pr-number: ${{ github.event.pull_request.number }} actor-login: ${{ github.event.review.user.login }} azure-openai-endpoint: ${{ vars.AZURE_OPENAI_ENDPOINT }} @@ -50,10 +50,10 @@ jobs: github.event.comment.user.type != 'Bot' && startsWith(github.event.comment.body, '@simplycubed-code') && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) - uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.7 + uses: simplycubed/code/.github/workflows/simplycubed.yml@v0.1.8 with: ref: ${{ github.event.issue.number }} - github-app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + github-app-client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} comment-body: ${{ github.event.comment.body }} issue-number: ${{ github.event.issue.pull_request == null && github.event.issue.number || '' }} pr-number: ${{ github.event.issue.pull_request != null && github.event.issue.number || '' }} diff --git a/docs/templates/simplycubed-selftest.yml b/docs/templates/simplycubed-selftest.yml index 5ce466a..eaff259 100644 --- a/docs/templates/simplycubed-selftest.yml +++ b/docs/templates/simplycubed-selftest.yml @@ -34,7 +34,7 @@ jobs: id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: - app-id: ${{ vars.SIMPLYCUBED_GH_APP_ID }} + client-id: ${{ vars.SIMPLYCUBED_GH_APP_CLIENT_ID }} private-key: ${{ secrets.SIMPLYCUBED_GH_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: ${{ github.event.repository.name }} diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 48f797a..485ddcc 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -92,7 +92,8 @@ Pull requests opened with a `GITHUB_TOKEN` do not trigger other workflows. If your required checks never appear on the agent's pull requests, the run is authenticating with the default token rather than the App. -Check that `SIMPLYCUBED_GH_APP_ID` and `SIMPLYCUBED_GH_APP_PRIVATE_KEY` are set. +Check that `SIMPLYCUBED_GH_APP_CLIENT_ID` and `SIMPLYCUBED_GH_APP_PRIVATE_KEY` +are set. The self-test's first step fails when they are missing or wrong. ## The run was refused before it started diff --git a/scripts/check-workflows.sh b/scripts/check-workflows.sh index 90e9d3f..d0284fe 100755 --- a/scripts/check-workflows.sh +++ b/scripts/check-workflows.sh @@ -16,12 +16,43 @@ if grep -rIn --exclude-dir=.git -E '^(<{7}|={7}|>{7})( |$)' . 2>/dev/null; then fail=1 fi -# Workflow files have to parse. Without this nothing in the gate reads them. +# Workflow files have to parse, and no mapping may repeat a key. Duplicate keys +# matter more than they look: yaml.safe_load accepts them and keeps the last one, +# so a second `env:` in a step silently discards the first. GitHub is stricter +# and refuses to start the run at all. That combination is the worst one, a green +# gate and a workflow that never executes, and it is how v0.1.7 shipped with +# GH_TOKEN and both Azure variables dropped from the step that needs them. for f in .github/workflows/*.yml docs/templates/*.yml cmd/simplycubed/*.yml.tmpl; do [ -e "$f" ] || continue # The embedded template carries a placeholder tag that is substituted at # render time; it is still valid YAML. - if ! python3 -c "import sys,yaml; yaml.safe_load(open(sys.argv[1]))" "$f" 2>/dev/null; then + if ! python3 - "$f" <<'PY' 2>&1 +import sys, yaml + +class StrictLoader(yaml.SafeLoader): + pass + +def no_duplicates(loader, node, deep=False): + seen = set() + for key_node, _ in node.value: + key = loader.construct_object(key_node, deep=deep) + if key in seen: + raise yaml.YAMLError( + "duplicate key %r at line %d" % (key, key_node.start_mark.line + 1) + ) + seen.add(key) + return yaml.SafeLoader.construct_mapping(loader, node, deep) + +StrictLoader.add_constructor( + yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, no_duplicates +) + +try: + yaml.load(open(sys.argv[1]), Loader=StrictLoader) +except Exception as exc: + sys.exit(str(exc)) +PY + then echo "not valid YAML: $f" >&2 fail=1 fi