Skip to content

feat: actionlint and check-jsonschema composite actions - #13

Merged
kyle-sexton merged 1 commit into
mainfrom
feat/phase2-actionlint-jsonschema
Jun 23, 2026
Merged

feat: actionlint and check-jsonschema composite actions#13
kyle-sexton merged 1 commit into
mainfrom
feat/phase2-actionlint-jsonschema

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Phase 2 of the CI de-duplication program — first pair: the two single-tool step lanes that lift as composite actions (architecture D1).

What

  • actionlint — GitHub Actions workflow linter. Self-contained curl + sha256 install (v1.7.12, hash corroborated by the upstream checksums.txt and an independent local compute), the repo's established single-binary idiom (shellcheck/editorconfig/lychee-offline). Bare run auto-discovers .github/workflows; the runner's shellcheck lints embedded run: scripts. Optional color / config-file / version / sha256 inputs (D4 open-closed).
  • check-jsonschema — JSON/YAML schema validator. Ephemeral uvx check-jsonschema@0.37.3 (the ruff/pyright idiom). One invocation = one schema source (builtin-schema or schemafile) + N files; a caller validates several schema groups by invoking once per group. Config-light — the tool reads no config file of its own, so no standards module is created (recorded in the research note).

Lift source & posture

Lifted from medley's yaml-ci.yml (actionlint 1.7.12; check-jsonschema multi-invocation pattern). Behavior preserved; backfilled optional inputs.

Config boundary

Neither tool needs upstream config. Both run config-light in their lifted form — no new standards module required for either (flagged per the program's config-boundary rule).

Dogfood (behind ci-status)

  • actionlint lints this repo's own workflows (strong dogfood).
  • check-jsonschema validates dependabot.yml (vendor.dependabot) and the workflow files (vendor.github-workflows).
  • The ci-status aggregation loop is rewritten with read -ra so it passes actionlint's shellcheck integration (root-cause fix, no suppression).

Verification

Both verified locally with the exact CI invocations: actionlint -color + shellcheck 0.11.0 (the runner's version) clean; both uvx check-jsonschema validations pass.

Research

docs/dedup-program/research/actionlint.md, docs/dedup-program/research/check-jsonschema.md (versions/assets/checksums/invocation, all verified against official sources 2026-06-23).

🤖 Generated with Claude Code

Phase 2 of the CI de-duplication program, first pair: the two single-tool
step lanes that lift as composite actions (D1).

- actionlint: self-contained curl + sha256 install (v1.7.12), the repo's
  single-binary idiom; auto-discovers .github/workflows and lints embedded
  run: scripts via the runner's shellcheck. Optional color/config-file/
  version/sha256 inputs (D4 open-closed).
- check-jsonschema: ephemeral uvx run (v0.37.3) like ruff/pyright. One
  invocation = one schema source (builtin-schema | schemafile) + N files;
  callers invoke once per schema group. Config-light — the tool reads no
  config file, so no standards module (research note records this).

Dogfooded behind ci-status: actionlint lints this repo's own workflows;
check-jsonschema validates dependabot.yml (vendor.dependabot) and the
workflow files (vendor.github-workflows). The ci-status aggregation loop is
rewritten with read -ra so it passes actionlint's shellcheck integration.

Both verified locally with the exact CI invocations (actionlint+shellcheck
0.11.0 clean; uvx check-jsonschema validations pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kyle-sexton
kyle-sexton merged commit 62235bb into main Jun 23, 2026
14 checks passed
@kyle-sexton
kyle-sexton deleted the feat/phase2-actionlint-jsonschema branch June 23, 2026 13:35
kyle-sexton added a commit that referenced this pull request Jul 16, 2026
## Summary

Step 1 of 3 for decision #13 (`metadata-do-not-merge-wire-or-walk-back`,
Decisions Log:
https://claude.ai/code/artifact/232ecdce-8316-4880-8c0a-dc3c7dcf3a63).

- `do-not-merge-gate.yml`: a new reusable workflow mirroring
`semantic-pr.yml`'s shape exactly (same `prerequisite-result`
fail-closed pattern, same runner-selection input). Fails the job while
the calling PR carries a configured label (default `do-not-merge`).
- README: documents the canonical caller block, matching the existing
`semantic-pr` doc entry's format.

## Why a new reusable workflow, not a ruleset rule

`github-iac`'s `Labels.cs` has declared `do-not-merge` as a "Hard merge
gate" since it was introduced, but nothing has ever enforced it. GitHub
Rulesets have **no native label-condition rule type** — confirmed
empirically by enumerating every `OrganizationRulesetRules*` type in the
`pulumi-github` v6.14.0 provider assembly. A required-status-check is
the only real mechanism, so this follows the exact precedent
`pr-title`/`semantic-pr` already established in this repo.

## Re-evaluation on label change

A status check binds to a SHA. If it runs once (no label) and passes,
then someone adds `do-not-merge`, nothing re-runs and the merge isn't
actually blocked. The canonical caller block triggers on
`labeled`/`unlabeled` (in addition to
`opened`/`reopened`/`synchronize`/`merge_group`) specifically so the
gate re-fires when the label is toggled.

## Rollout sequencing (this PR is step 1 only)

1. **This PR** — land the reusable workflow.
2. Once merged, add the canonical caller to every `requires-ci` repo (9
repos: `.github`, `ci-runner`, `ci-workflows`, `claude-code-plugins`,
`github-iac`, `medley`, `standards`, `dotfiles`, `provisioning`), pinned
to this PR's merge commit SHA.
3. Only after all 9 callers are merged and emitting the check: add
`do-not-merge / do-not-merge` to `github-iac`'s `ci-gate`
`RequiredStatusChecks` (OrgRulesets.cs) — never before, per this repo's
own documented rule ("open PRs block on a check that never runs").

Scope confirmed with the repo owner: `requires-ci` repos only (not the 6
`RequiresCi: false` archived/content repos), caller-workflow mechanism
(not `required_workflows`, since that ruleset primitive's
re-evaluation-on-label-toggle behavior is unverified).

## Verification

- `actionlint .github/workflows/do-not-merge-gate.yml` — clean.
- `zizmor .github/workflows/do-not-merge-gate.yml` — no findings.
- Repo's own lefthook pre-commit hooks passed at commit time.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant