Skip to content

Commit 7736a48

Browse files
committed
Add GitHub Actions distribution channel
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
1 parent 03b0e91 commit 7736a48

7 files changed

Lines changed: 232 additions & 0 deletions

File tree

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ row: "- [{summary}](../{filename})"
5454
- [Rebase, CI monitoring, and review comment resolution.](../docs/development/pr-fixup-workflow.md)
5555
- [The `jeduden/asdf-mdsmith` plugin installs the checksum-verified prebuilt binary; the short form awaits the asdf-plugins registry entry.](../docs/development/release-channels/asdf.md)
5656
- [A single-file `.flatpak` bundle built in CI from the x86_64 Linux release binary and attached to each GitHub release, installed by file with host filesystem access for the linter.](../docs/development/release-channels/flatpak.md)
57+
- [A composite action at the repository root downloads the checksum-verified release binary for the runner's OS and architecture, puts `mdsmith` on `PATH`, and runs the command in its `args` input; referenced as `uses: jeduden/mdsmith@<ref>`.](../docs/development/release-channels/github-actions.md)
5758
- [Per-platform mdsmith binaries plus the .vsix, the checksum file, and a Sigstore signature, attached to a tag-named release.](../docs/development/release-channels/github-releases.md)
5859
- [`go install` compiles mdsmith from the tagged module source with the host Go 1.25+ toolchain; no prebuilt binary is downloaded.](../docs/development/release-channels/go.md)
5960
- [The `jeduden/homebrew-mdsmith` tap installs the checksum-verified prebuilt binary for macOS or Linux on Intel or arm64.](../docs/development/release-channels/homebrew.md)

.github/workflows/action-smoke.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Action smoke test
2+
3+
# Exercise the root composite action (action.yml) end-to-end on every
4+
# runner OS it claims to support, so a break in the OS/arch mapping, the
5+
# checksum verification, or the PATH wiring fails the PR rather than a
6+
# downstream user's workflow. It installs a pinned past release, so the
7+
# test is deterministic and does not depend on this PR being released yet.
8+
on:
9+
push:
10+
branches: [main]
11+
paths:
12+
- "action.yml"
13+
- ".github/workflows/action-smoke.yml"
14+
pull_request:
15+
branches: [main]
16+
paths:
17+
- "action.yml"
18+
- ".github/workflows/action-smoke.yml"
19+
20+
permissions:
21+
contents: read
22+
23+
jobs:
24+
smoke:
25+
name: Install and run (${{ matrix.os }})
26+
runs-on: ${{ matrix.os }}
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
os: [ubuntu-latest, macos-latest, windows-latest]
31+
steps:
32+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
33+
with:
34+
persist-credentials: false
35+
36+
- id: mdsmith
37+
uses: ./
38+
with:
39+
# A real, immutable past release so the download is deterministic.
40+
version: v0.41.0
41+
args: version
42+
43+
- name: Verify mdsmith stayed on PATH and reported a version
44+
shell: bash
45+
env:
46+
GOT_VERSION: ${{ steps.mdsmith.outputs.version }}
47+
run: |
48+
mdsmith version
49+
test -n "$GOT_VERSION"

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ row: "- [{summary}]({filename})"
6060
- [Rebase, CI monitoring, and review comment resolution.](docs/development/pr-fixup-workflow.md)
6161
- [The `jeduden/asdf-mdsmith` plugin installs the checksum-verified prebuilt binary; the short form awaits the asdf-plugins registry entry.](docs/development/release-channels/asdf.md)
6262
- [A single-file `.flatpak` bundle built in CI from the x86_64 Linux release binary and attached to each GitHub release, installed by file with host filesystem access for the linter.](docs/development/release-channels/flatpak.md)
63+
- [A composite action at the repository root downloads the checksum-verified release binary for the runner's OS and architecture, puts `mdsmith` on `PATH`, and runs the command in its `args` input; referenced as `uses: jeduden/mdsmith@<ref>`.](docs/development/release-channels/github-actions.md)
6364
- [Per-platform mdsmith binaries plus the .vsix, the checksum file, and a Sigstore signature, attached to a tag-named release.](docs/development/release-channels/github-releases.md)
6465
- [`go install` compiles mdsmith from the tagged module source with the host Go 1.25+ toolchain; no prebuilt binary is downloaded.](docs/development/release-channels/go.md)
6566
- [The `jeduden/homebrew-mdsmith` tap installs the checksum-verified prebuilt binary for macOS or Linux on Intel or arm64.](docs/development/release-channels/homebrew.md)

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ row: "- [{summary}]({filename})"
4646
- [Rebase, CI monitoring, and review comment resolution.](docs/development/pr-fixup-workflow.md)
4747
- [The `jeduden/asdf-mdsmith` plugin installs the checksum-verified prebuilt binary; the short form awaits the asdf-plugins registry entry.](docs/development/release-channels/asdf.md)
4848
- [A single-file `.flatpak` bundle built in CI from the x86_64 Linux release binary and attached to each GitHub release, installed by file with host filesystem access for the linter.](docs/development/release-channels/flatpak.md)
49+
- [A composite action at the repository root downloads the checksum-verified release binary for the runner's OS and architecture, puts `mdsmith` on `PATH`, and runs the command in its `args` input; referenced as `uses: jeduden/mdsmith@<ref>`.](docs/development/release-channels/github-actions.md)
4950
- [Per-platform mdsmith binaries plus the .vsix, the checksum file, and a Sigstore signature, attached to a tag-named release.](docs/development/release-channels/github-releases.md)
5051
- [`go install` compiles mdsmith from the tagged module source with the host Go 1.25+ toolchain; no prebuilt binary is downloaded.](docs/development/release-channels/go.md)
5152
- [The `jeduden/homebrew-mdsmith` tap installs the checksum-verified prebuilt binary for macOS or Linux on Intel or arm64.](docs/development/release-channels/homebrew.md)

action.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: mdsmith Markdown linter
2+
description: >-
3+
Install the mdsmith Markdown linter from a checksum-verified GitHub release
4+
binary for the runner's OS and architecture, put it on PATH, and optionally
5+
run a mdsmith command.
6+
author: jeduden
7+
branding:
8+
icon: check-square
9+
color: purple
10+
11+
inputs:
12+
version:
13+
description: >-
14+
mdsmith release to install: a release tag such as "v0.41.0", or "latest"
15+
to fetch the most recent release.
16+
required: false
17+
default: latest
18+
args:
19+
description: >-
20+
Arguments passed to mdsmith after install, split on whitespace
21+
(for example "check ."). Leave empty to only put mdsmith on PATH.
22+
required: false
23+
default: ""
24+
working-directory:
25+
description: Directory the mdsmith command runs in when "args" is set.
26+
required: false
27+
default: "."
28+
29+
outputs:
30+
version:
31+
description: The version string reported by the installed mdsmith binary.
32+
value: ${{ steps.install.outputs.version }}
33+
34+
runs:
35+
using: composite
36+
steps:
37+
- id: install
38+
shell: bash
39+
# Inputs flow in through env, never interpolated into the script body,
40+
# so a crafted input cannot inject shell commands.
41+
env:
42+
MDSMITH_VERSION: ${{ inputs.version }}
43+
# The binary is downloaded over HTTPS and SHA256-verified against the
44+
# release checksums.txt before its directory is appended to PATH, so the
45+
# github-path write is safe to ignore.
46+
run: | # zizmor: ignore[github-env]
47+
set -euo pipefail
48+
49+
# Map the runner OS/arch onto the published release-asset name.
50+
case "$RUNNER_OS" in
51+
Linux) os=linux ; ext="" ;;
52+
macOS) os=darwin ; ext="" ;;
53+
Windows) os=windows; ext=".exe" ;;
54+
*) echo "::error::unsupported runner OS: $RUNNER_OS"; exit 1 ;;
55+
esac
56+
case "$RUNNER_ARCH" in
57+
X64) arch=amd64 ;;
58+
ARM64) arch=arm64 ;;
59+
*) echo "::error::unsupported runner arch: $RUNNER_ARCH"; exit 1 ;;
60+
esac
61+
if [ "$os" = windows ] && [ "$arch" != amd64 ]; then
62+
echo "::error::mdsmith ships a windows-amd64 build only, not windows-$arch"
63+
exit 1
64+
fi
65+
asset="mdsmith-${os}-${arch}${ext}"
66+
67+
if [ "$MDSMITH_VERSION" = latest ]; then
68+
base="https://github.com/jeduden/mdsmith/releases/latest/download"
69+
else
70+
base="https://github.com/jeduden/mdsmith/releases/download/${MDSMITH_VERSION}"
71+
fi
72+
73+
dest="${RUNNER_TEMP}/mdsmith-bin"
74+
mkdir -p "$dest"
75+
curl -fsSL --retry 3 --retry-delay 2 "${base}/${asset}" -o "${dest}/${asset}"
76+
curl -fsSL --retry 3 --retry-delay 2 "${base}/checksums.txt" -o "${dest}/checksums.txt"
77+
78+
# Verify the download against the release checksums file. macOS runners
79+
# have shasum but not GNU sha256sum, so fall back to it.
80+
expected="$(grep " ${asset}\$" "${dest}/checksums.txt" | awk '{print $1}' | head -n1)"
81+
if [ -z "$expected" ]; then
82+
echo "::error::${asset} not listed in checksums.txt"
83+
exit 1
84+
fi
85+
if command -v sha256sum >/dev/null 2>&1; then
86+
actual="$(sha256sum "${dest}/${asset}" | awk '{print $1}')"
87+
else
88+
actual="$(shasum -a 256 "${dest}/${asset}" | awk '{print $1}')"
89+
fi
90+
if [ "$expected" != "$actual" ]; then
91+
echo "::error::checksum mismatch for ${asset}: expected ${expected}, got ${actual}"
92+
exit 1
93+
fi
94+
95+
bin="mdsmith${ext}"
96+
mv "${dest}/${asset}" "${dest}/${bin}"
97+
chmod +x "${dest}/${bin}"
98+
echo "$dest" >> "$GITHUB_PATH"
99+
echo "version=$("${dest}/${bin}" version)" >> "$GITHUB_OUTPUT"
100+
101+
- if: ${{ inputs.args != '' }}
102+
shell: bash
103+
working-directory: ${{ inputs.working-directory }}
104+
env:
105+
MDSMITH_ARGS: ${{ inputs.args }}
106+
# MDSMITH_ARGS is intentionally unquoted so "check ." splits into
107+
# separate arguments.
108+
run: mdsmith $MDSMITH_ARGS
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: GitHub Actions
3+
summary: >-
4+
A composite action at the repository root downloads the
5+
checksum-verified release binary for the runner's OS and
6+
architecture, puts `mdsmith` on `PATH`, and runs the
7+
command in its `args` input; referenced as
8+
`uses: jeduden/mdsmith@<ref>`.
9+
mechanism: pull
10+
artifact: cli
11+
command: "uses: jeduden/mdsmith@v0"
12+
audience: Linting Markdown inside GitHub Actions CI
13+
platforms: [linux, macos, windows]
14+
channelurl: https://github.com/jeduden/mdsmith
15+
weight: 15
16+
unlisted: true
17+
---
18+
# GitHub Actions
19+
20+
Release page: <https://github.com/jeduden/mdsmith>
21+
22+
The repository root carries an `action.yml`, so a workflow
23+
step runs mdsmith with:
24+
25+
```yaml
26+
- uses: jeduden/mdsmith@v0
27+
with:
28+
version: latest # a release tag like v0.41.0, or latest
29+
args: check . # omit to only put mdsmith on PATH
30+
```
31+
32+
The composite action reads `$RUNNER_OS` and
33+
`$RUNNER_ARCH`. It maps them to the matching release
34+
asset — `mdsmith-linux-amd64`, `mdsmith-darwin-arm64`,
35+
`mdsmith-windows-amd64.exe`, and the rest. It downloads
36+
that asset over HTTPS. Then it verifies the SHA-256
37+
against the release's `checksums.txt` before it adds the
38+
binary to `PATH`.
39+
40+
macOS runners fall back to `shasum -a 256`, since they
41+
ship no GNU `sha256sum`. Windows runners get the one
42+
`windows-amd64` build. Any other Windows architecture
43+
fails with a clear error, not a 404.
44+
45+
Three inputs drive it. `version` selects the release —
46+
`latest` (the default) or a tag such as `v0.41.0`. `args`,
47+
when non-empty, is split on whitespace and passed to
48+
`mdsmith`; an empty `args` only installs the binary so a
49+
later step can call it. `working-directory` sets the
50+
directory the `args` command runs in. The action exposes
51+
one output, `version`, the string `mdsmith version` prints.
52+
53+
For a locked-down supply chain, pin `uses:` to a release
54+
tag or a commit SHA, the way this repository pins every
55+
third-party action it consumes.
56+
57+
The short `uses: jeduden/mdsmith@v0` form needs two
58+
things. A tagged release must ship this `action.yml`. The
59+
floating `v0` tag must then move onto it. Until that
60+
happens, pin the action to a commit SHA or use `@main`.
61+
You can also skip the action and run the release binary in
62+
a `run:` step. That repeats by hand the download and
63+
verify steps the action automates.
64+
65+
Because no published tag installs the action yet, this
66+
channel sets `unlisted: true` in its frontmatter, so
67+
`sync-channels` keeps it out of the website install picker
68+
and the install-guide table excludes it by glob. The
69+
`action.yml` and this doc stay; only the user-facing
70+
listings wait for a release to carry the action. Drop both
71+
once `uses: jeduden/mdsmith@v0` resolves.

docs/guides/install.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ glob:
4343
- "../development/release-channels/*.md"
4444
- "!../development/release-channels/proto.md"
4545
- "!../development/release-channels/winget.md"
46+
- "!../development/release-channels/github-actions.md"
4647
where: 'artifact: "cli"'
4748
sort: numeric:weight
4849
header: |

0 commit comments

Comments
 (0)