diff --git a/.github/scripts/hub-reenable-check.sh b/.github/scripts/hub-reenable-check.sh index 6d2d44a6a..09dc8d71e 100755 --- a/.github/scripts/hub-reenable-check.sh +++ b/.github/scripts/hub-reenable-check.sh @@ -220,10 +220,12 @@ operation(s) get their tests back: ${ops}." >/dev/null GH_TOKEN="$GH_TOKEN_GENERATOR" gh label create nightly-api-fix --repo "$GEN_REPO" --color FF4444 \ --description "Bot-opened fix PR for a nightly triage finding (test-generation bug or coverage gap)" 2>/dev/null || true + GH_TOKEN="$GH_TOKEN_GENERATOR" gh label create hub --repo "$GEN_REPO" --color 1D76DB \ + --description "Hub-related" 2>/dev/null || true pr_url="$(GH_TOKEN="$GH_TOKEN_GENERATOR" gh pr create --repo "$GEN_REPO" --base main --head "$branch" --draft \ --title "chore(nightly): re-enable ${ops} — camunda-hub#${issue_num} closed" \ - --body-file "$body_file" --label nightly-api-fix 2>&1)" + --body-file "$body_file" --label nightly-api-fix --label hub 2>&1)" create_rc=$? rm -f "$body_file" diff --git a/.github/scripts/spec-bump-common.sh b/.github/scripts/spec-bump-common.sh index db028206b..2316cfe4a 100644 --- a/.github/scripts/spec-bump-common.sh +++ b/.github/scripts/spec-bump-common.sh @@ -16,6 +16,10 @@ run_url="${GITHUB_SERVER_URL:-https://github.com}/${GITHUB_REPOSITORY:-}/actions # The rolling auto-bump PR's branch for the active config. bump_branch() { echo "chore/spec-bump-${CONFIG:?CONFIG required}"; } +# The label that marks Hub work, for the Hub config only: the spec-bump check also runs for +# camunda-oca, whose PRs and issues must not carry it. Empty for any other config. +config_label() { if [ "${CONFIG:-}" = camunda-hub ]; then echo hub; fi; } + # Number of the open rolling tracking issue whose title is exactly $ISSUE_TITLE, # or empty. The first match is selected inside jq (`first // empty`) rather than # piped to `head -1`: under `set -euo pipefail`, `head` closing the pipe can diff --git a/.github/scripts/spec-bump-open-pr.sh b/.github/scripts/spec-bump-open-pr.sh index 9aa592a68..6b2ac5f73 100755 --- a/.github/scripts/spec-bump-open-pr.sh +++ b/.github/scripts/spec-bump-open-pr.sh @@ -39,6 +39,12 @@ short="${LATEST:0:12}" # can reach a `gh pr edit` before the later creation calls run. gh label create "$DRIFT_LABEL" --color BFD4F2 --description "Upstream spec drifted from the pin (spec-bump check)" 2>/dev/null || true gh label create auto-generated --color ededed --description "Opened by automation, not a human" 2>/dev/null || true +# Hub's bump PR also carries `hub`. Added with a separate, best-effort edit (not `--label` on create), +# so a label that failed to create can never lose the PR itself. +hub_label="$(config_label)" +if [ -n "$hub_label" ]; then + gh label create "$hub_label" --color 1D76DB --description "Hub-related" 2>/dev/null || true +fi # If a bump PR is already open, leave it alone — it may carry reviewer edits # (e.g. invariant updates), and force-pushing the rolling branch would clobber @@ -54,6 +60,7 @@ if [ -n "$existing" ]; then # superseded tracking issue below (labeling is an auxiliary self-heal, the # issue-close is the actual point of this path). gh pr edit "$existing" --add-label "$DRIFT_LABEL" --add-label auto-generated >/dev/null || true + if [ -n "$hub_label" ]; then gh pr edit "$existing" --add-label "$hub_label" >/dev/null || true; fi issue="$(find_rolling_issue)" if [ -n "$issue" ]; then gh issue close "$issue" --comment "Superseded by the open auto-bump PR #${existing}. Closing." >/dev/null @@ -135,6 +142,7 @@ title="chore(${CONFIG}): bump spec pin to ${short}" echo "Opening bump PR." gh pr create --draft --base main --head "$branch" --title "$title" --body-file "$body_file" \ --label "$DRIFT_LABEL" --label auto-generated >/dev/null +if [ -n "$hub_label" ]; then gh pr edit "$branch" --add-label "$hub_label" >/dev/null || true; fi # Clean up the tracking issue if one is open — the PR supersedes it. issue="$(find_rolling_issue)" diff --git a/.github/scripts/spec-bump-report.sh b/.github/scripts/spec-bump-report.sh index a86bdaf00..5e4c6952b 100755 --- a/.github/scripts/spec-bump-report.sh +++ b/.github/scripts/spec-bump-report.sh @@ -79,6 +79,10 @@ body_file="$(mktemp)" # on whether THIS run's blocker is an uncovered operation (#475's gate). gh label create "$DRIFT_LABEL" --color BFD4F2 --description "Upstream spec drifted from the pin (spec-bump check)" 2>/dev/null || true gh label create auto-generated --color ededed --description "Opened by automation, not a human" 2>/dev/null || true +hub_label="$(config_label)" +if [ -n "$hub_label" ]; then + gh label create "$hub_label" --color 1D76DB --description "Hub-related" 2>/dev/null || true +fi gh label create missing-coverage --color D93F0B --description "A spec operation has no generated test coverage" 2>/dev/null || true gh label create needs-fixture --color D93F0B --description "A newly-required request property has no existing fixture (#492)" 2>/dev/null || true @@ -94,6 +98,7 @@ if [ -n "$existing" ]; then # Best-effort (labeling is an auxiliary signal): a transient API error or a # label that failed to create above must not abort the issue update itself. gh issue edit "$existing" --add-label "$DRIFT_LABEL" --add-label auto-generated >/dev/null || true + if [ -n "$hub_label" ]; then gh issue edit "$existing" --add-label "$hub_label" >/dev/null || true; fi # Sync missing-coverage to THIS run's state — add it when unmapped ops are # the blocker, remove it if a later run clears them but the issue stays open # for another reason (e.g. invariants still broken). Both best-effort, same @@ -119,6 +124,7 @@ else # entirely rather than just the label. Add it separately, best-effort, after. new_url="$(gh issue create --title "$ISSUE_TITLE" --body-file "$body_file" --label "$DRIFT_LABEL" --label auto-generated)" echo "Opened ${new_url}" + if [ -n "$hub_label" ]; then gh issue edit "${new_url##*/}" --add-label "$hub_label" >/dev/null || true; fi if [ -n "$UNMAPPED" ]; then gh issue edit "${new_url##*/}" --add-label missing-coverage >/dev/null || true fi diff --git a/tests/request-validation/hub-label-automation.test.ts b/tests/request-validation/hub-label-automation.test.ts new file mode 100644 index 000000000..d1d7fffe9 --- /dev/null +++ b/tests/request-validation/hub-label-automation.test.ts @@ -0,0 +1,41 @@ +import { execFileSync } from 'node:child_process'; +import { readFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const scripts = join(dirname(fileURLToPath(import.meta.url)), '../../.github/scripts'); +const read = (name: string) => readFileSync(join(scripts, name), 'utf8'); + +function configLabel(config: string): string { + return execFileSync( + 'bash', + ['-c', `source "${join(scripts, 'spec-bump-common.sh')}"; config_label`], + { env: { ...process.env, CONFIG: config }, encoding: 'utf8' }, + ).trim(); +} + +describe('the hub label on automation PRs and issues', () => { + it('marks Hub work with the hub label, and camunda-oca work with nothing', () => { + expect(configLabel('camunda-hub')).toBe('hub'); + expect(configLabel('camunda-oca')).toBe(''); + }); + + it('adds it to the spec-bump PR when it opens, and when it finds one already open', () => { + const src = read('spec-bump-open-pr.sh'); + expect(src).toContain('hub_label="$(config_label)"'); + expect(src).toContain('gh pr edit "$existing" --add-label "$hub_label"'); + expect(src).toContain('gh pr edit "$branch" --add-label "$hub_label"'); + }); + + it('adds it to the spec-bump tracking issue when it opens, and on every update', () => { + const src = read('spec-bump-report.sh'); + expect(src).toContain('hub_label="$(config_label)"'); + expect(src).toContain('gh issue edit "$existing" --add-label "$hub_label"'); + expect(src).toContain(`gh issue edit "\${new_url##*/}" --add-label "$hub_label"`); + }); + + it('opens the re-enable PR with the hub label', () => { + expect(read('hub-reenable-check.sh')).toContain('--label nightly-api-fix --label hub'); + }); +});