Skip to content

Add GitHub Actions distribution channel - #623

Merged
jeduden merged 8 commits into
mainfrom
claude/festive-albattani-xxpq1y
Jun 14, 2026
Merged

Add GitHub Actions distribution channel#623
jeduden merged 8 commits into
mainfrom
claude/festive-albattani-xxpq1y

Conversation

@jeduden

@jeduden jeduden commented Jun 14, 2026

Copy link
Copy Markdown
Owner

What

Adds mdsmith as a GitHub Action, so a CI workflow can install and run it in one step.

- uses: jeduden/mdsmith@<commit-sha>   # vX.Y.Z  (pin a SHA, or a release tag)
  with:
    version: latest    # which mdsmith release to install (a tag, or latest)
    args: check .      # omit to only put mdsmith on PATH

How

  • action.yml (repo root) — a composite action: it maps $RUNNER_OS/$RUNNER_ARCH to the matching release asset, downloads it, verifies the SHA-256 against the release checksums.txt, puts mdsmith on PATH, and optionally runs args. Cross-platform (Linux/macOS/Windows; shasum -a 256 fallback where GNU sha256sum is absent; windows-amd64 only). Inputs version (default latest), args, working-directory; output version. Inputs flow through env:, never interpolated into the script body — the same hardening as setup-mdsmith-pinned-version.
  • docs/development/release-channels/github-actions.md — the release-channel registration (mechanism: push, GitHub Marketplace), the single source the install table, website picker, and "Available on" strip derive from.
  • .github/workflows/action-smoke.yml — a Linux/macOS/Windows matrix that installs a pinned release and asserts the reported version, exercising the OS/arch mapping, checksum path, and PATH wiring.
  • mdsmith fix propagated the catalog summary into CLAUDE.md, AGENTS.md, .github/copilot-instructions.md.

Pinning & Marketplace

  • Pin uses: to a commit SHA (strongest) or an immutable release tag — the repo's own convention. There is no floating @v0 tag: a GITHUB_TOKEN-published release can't trigger the workflow that would maintain one (see Review), so it would silently never move.
  • The action publishes to the GitHub Marketplace as part of a release — publishing the draft (the release job's final step) updates the listing. The channel is unlisted: true until that first publish, so it stays out of the "Available on" strip, the picker, and the install/release tables — no dead links. Going live is a documented one-line flip after the maintainer accepts the one-time Marketplace Developer Agreement (tracked as Operational Checklist item 8 in release.md).

Review — 2× /code-review (xhigh)

  • Dropped a @v0 floating-tag workflow that could never fire: GitHub doesn't let a GITHUB_TOKEN-published release trigger another workflow, so @v0 would never advance. Replaced with SHA / release-tag pinning (zero automation), which also makes job: release / credential: GITHUB_TOKEN accurate.
  • action.yml: the "not listed in checksums" error was dead code under set -euo pipefailawk extraction (also handles binary-mode checksums, drops the SIGPIPE-prone head); the GITHUB_OUTPUT write captures mdsmith version first so a non-zero exit can't leave a dangling heredoc; corrected the args comment.
  • Smoke test asserts the version output content, not just non-empty.
  • Docs use a generic vX.Y.Z (the concrete v0.41.0 predates action.yml) and decouple the binary version: input from the action ref.

Testing

mdsmith check clean (482 files) · sync-channels --check drift-free · zizmor clean on action.yml + the workflow · smoke matrix green on Linux/macOS/Windows · end-to-end install verified against the real release binary (checksums.txt matched).

Commits are unsigned: the sandbox's commit-signing server returns HTTP 400 (also the only local go test failure — TestPGOMergeNoOutput, which does a git commit). Unrelated to this change; no Go code was added.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC

@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.50%. Comparing base (ac65a9b) to head (6e4d6e1).

Additional details and impacted files
Components Coverage Δ
Go 98.49% <ø> (ø)
TypeScript 99.53% <ø> (ø)

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jeduden
jeduden marked this pull request as ready for review June 14, 2026 22:33
@jeduden
jeduden force-pushed the claude/festive-albattani-xxpq1y branch from 2e569a2 to 47e3f4d Compare June 14, 2026 23:11
claude added 8 commits June 15, 2026 01:19
Ship mdsmith as a composite GitHub Action via a root action.yml. It
downloads the checksum-verified release binary for the runner's OS and
architecture, puts mdsmith on PATH, and optionally runs a command from
its args input (version, args, and working-directory inputs; a version
output).

Register it as a release channel under docs/development/release-channels/.
Like the WinGet channel it is unlisted until a tagged release ships the
action and a floating v0 tag resolves uses: jeduden/mdsmith@v0: the
install-guide table excludes it by glob and sync-channels keeps it out of
the website install picker. mdsmith fix propagated the catalog summary
into CLAUDE.md and its generated mirrors.

Add a cross-platform smoke-test workflow that installs a pinned past
release on ubuntu, macos, and windows runners, exercising the OS/arch
mapping, checksum verification (sha256sum with a shasum fallback for
macOS), and PATH wiring.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
Windows runners return $RUNNER_TEMP as a backslash path. GNU coreutils
sha256sum escapes a backslash in the checksummed file path by prefixing
the hash with one, so the computed hash gained a leading backslash and
never matched the clean hash from checksums.txt. The cross-platform
smoke test caught it: ubuntu and macos passed, windows failed.

Normalize the runner temp path's backslashes to forward slashes before
building any path from it. The forward-slash form also resolves cleanly
for the GITHUB_PATH write the bash steps read back.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
Lead the channel doc's usage example and guidance with pinning uses: to
a full-length commit SHA rather than a version tag, matching what GitHub
recommends and what this repository already does for every third-party
action. Clarify the two distinct controls: the SHA pins the action ref,
and the action's checksum verification pins the release binary it
downloads, so the version: input stays a release tag by design.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
Distinguish mdsmith's immutable release tags from the floating @v0
convenience tag: a release-tag pin like @v0.41.0 is a safe, reproducible
alternative, while only @v0 moves by design. The commit SHA stays the
strongest pin because it can never move.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
Model the GitHub Actions channel as a push channel so it surfaces in the
"Available on" strip on mdsmith.dev (the strip filters to mechanism: push)
alongside the install picker and table:

- Switch the channel to mechanism: push with registry github.com/marketplace,
  credential GITHUB_TOKEN, job release, and a Marketplace channel URL; drop
  unlisted and the install-table glob exclusion. The release job drafts a
  release that carries action.yml; publishing it adds/updates the Marketplace
  listing (one-time Developer Agreement acceptance required).
- Name the action "mdsmith" for a clean Marketplace slug.
- Add a marketplace-major-tag workflow that, on release publish, moves the
  major-version tag (v0) onto the release so uses: jeduden/mdsmith@v0 tracks
  the latest 0.x build. It pushes via a masked http.extraheader with
  persist-credentials: false, matching the benchmark-publish pattern.

Regenerate channels.yaml and the catalogs; tighten one line of release.md
prose so its push-channels table stays within the file-length budget.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
The Marketplace listing and @v0 only resolve after the one-time Developer
Agreement acceptance and the first release that ships action.yml. Listing
it before then would show a dead "Available on" link, so hide it until live
(the WinGet pattern):

- Set unlisted: true on the channel; sync-channels keeps it out of the
  website install picker and the "Available on" strip.
- Re-add the install-guide table glob exclusion, and exclude it from the
  release-pipeline push table too (Marketplace publish is a manual checkbox,
  not a credentialed automated job).
- Add Operational Checklist item 8 in release.md: accept the Marketplace
  agreement on the first action release. The channel doc carries the full
  one-time steps and the flip-when-live instructions.

The action.yml, the marketplace-major-tag workflow, and the docs stay in
place; only the user-facing listings wait for the first publish.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
/code-review (xhigh) surfaced:

- marketplace-major-tag.yml never fires: a GITHUB_TOKEN-published release
  does not trigger workflows (GitHub anti-recursion), so @v0 never moved.
  Drop the @v0 floating tag and delete the workflow; recommend commit-SHA
  (strongest) or immutable release-tag pinning, which need no automation.
  The release job's publish step is what updates the Marketplace listing,
  so job: release / credential: GITHUB_TOKEN are now accurate.
- action.yml checksum: the `-z "$expected"` guard was dead under
  set -euo pipefail (the grep | head pipeline tripped pipefail before the
  empty check), so a missing asset aborted with no diagnostic. Switch to an
  awk match that exits 0 on no match, also tolerating binary-mode (*)
  checksums and dropping the SIGPIPE-prone head.
- action.yml: multiline-safe GITHUB_OUTPUT write; correct the args comment
  (the shell also glob-expands, not only whitespace-splits).
- action-smoke: assert the version output contains the pinned version
  rather than only checking it is non-empty.

mdsmith check clean, channels.yaml drift-free, zizmor clean.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
- action.yml: capture `mdsmith version` into a variable before the
  GITHUB_OUTPUT heredoc. A non-zero version exit now aborts cleanly (set -e)
  instead of leaving a dangling, unterminated `version<<EOF` that corrupts
  GITHUB_OUTPUT with "Matching delimiter not found".
- github-actions.md: stop presenting the concrete v0.41.0 as the action ref
  (that release predates action.yml). Use a vX.Y.Z placeholder, decouple the
  binary `version:` input (default latest) from the pinned action ref, and
  note to set `command` to the first action-bearing release tag at go-live.

https://claude.ai/code/session_01TKgJTS4UcFPqtdwkxYzTUC
@jeduden
jeduden force-pushed the claude/festive-albattani-xxpq1y branch from 47e3f4d to 6e4d6e1 Compare June 14, 2026 23:19
@jeduden
jeduden merged commit 7c68e77 into main Jun 14, 2026
38 checks passed
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.

2 participants