Skip to content

Commit 7137ddc

Browse files
author
merge-queue-bot
committed
Merge PR #432: Add a self-hosted Flatpak bundle release channel
2 parents 47f1c08 + da78a11 commit 7137ddc

15 files changed

Lines changed: 616 additions & 52 deletions

File tree

.github/copilot-instructions.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ row: "- [{summary}](../{filename})"
4848
- [The pkg/markdown public package: parse, produce, and its compatibility policy.](../docs/development/markdown-library.md)
4949
- [Label-driven merge queue workflow using jeduden/merge-queue-action.](../docs/development/merge-queue.md)
5050
- [Rebase, CI monitoring, and review comment resolution.](../docs/development/pr-fixup-workflow.md)
51+
- [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)
5152
- [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)
5253
- [Root `@mdsmith/cli` plus one platform-specific subpackage per supported host, all published via OIDC Trusted Publishing.](../docs/development/release-channels/npm.md)
5354
- [The same `.vsix` republished to Open VSX so VSCodium, Cursor, Theia, and Gitpod can install it.](../docs/development/release-channels/open-vsx.md)
5455
- [One platform-tagged wheel per supported host, published via OIDC Trusted Publishing.](../docs/development/release-channels/pypi.md)
5556
- [The mdsmith VS Code extension `.vsix`, published via a long-lived Marketplace publisher PAT.](../docs/development/release-channels/visual-studio-marketplace.md)
5657
- [Every GitHub Actions workflow that needs runtime logic invokes the `mdsmith-release` Go CLI rather than carrying inline shell or per-language scripts. This page captures the rule and the subcommands it applies to.](../docs/development/release-tooling.md)
57-
- [How a maintainer-dispatched workflow run publishes mdsmith to npm, PyPI, the Visual Studio Marketplace, Open VSX, and GitHub Releases — the workflow structure, the OIDC trusted publishers it relies on, the `release` environment that gates every publishing job, the separate website deploy, and the supply-chain hardening features baked into the pipeline.](../docs/development/release.md)
58+
- [How a maintainer-dispatched workflow run publishes mdsmith to npm, PyPI, the Visual Studio Marketplace, Open VSX, a Flatpak bundle, and GitHub Releases — the workflow structure, the OIDC trusted publishers it relies on, the `release` environment that gates every publishing job, the separate website deploy, and the supply-chain hardening features baked into the pipeline.](../docs/development/release.md)
5859
- [Rotation cadence and procedure for the long-lived publisher tokens consumed by the release and merge-queue workflows. Each tracked secret has its own file under `secret-rotations/`; the catalog below enumerates them. The scheduled reminder workflow consumes the same files and opens a GitHub issue when any secret is within 30 days of expiry.](../docs/development/secret-rotations.md)
5960
- [GitHub fine-grained PAT for the merge-queue action. Plain repo secret — not gated by an environment.](../docs/development/secret-rotations/merge-queue-token.md)
6061
- [Open VSX publisher token. Drives the `ovsx publish` step.](../docs/development/secret-rotations/ovsx-pat.md)
@@ -89,7 +90,7 @@ row: "- [{summary}](../{filename})"
8990
- [When a Markdown file's payload is prose, put it in the body under H2 sections — not in YAML frontmatter. `mdsmith extract` projects body structure into a JSON tree the same way it projects frontmatter, so the file stays editable as Markdown.](../docs/guides/extract-markdown-as-data.md)
9091
- [How to declare file kinds, assign files to them, and read the merged rule config that results.](../docs/guides/file-kinds.md)
9192
- [User guides for mdsmith directives, structure enforcement, and migration.](../docs/guides/index.md)
92-
- [Every channel that ships the mdsmith binary, the VS Code extension, or the Claude Code plugin — npm, PyPI, asdf, mise, the GitHub release, the Visual Studio Marketplace plus Open VSX, and the in-repository Claude Code marketplace — and which channel to pick for which workflow.](../docs/guides/install.md)
93+
- [Every channel that ships the mdsmith binary, the VS Code extension, or the Claude Code plugin — npm, PyPI, Homebrew, asdf, mise, a Flatpak bundle, the GitHub release, the Visual Studio Marketplace plus Open VSX, and the in-repository Claude Code marketplace — and which channel to pick for which workflow.](../docs/guides/install.md)
9394
- [Trade-offs and threshold guidance for readability, structure, length, and token budgets.](../docs/guides/metrics-tradeoffs.md)
9495
- [Move a project from markdownlint-cli or markdownlint-cli2 to mdsmith — the rule mapping, the config rewrite, and the markdownlint-to-mdsmith rule correspondence.](../docs/guides/migrate-from-markdownlint.md)
9596
- [Use `<?catalog?>` with a per-file `summary` front matter field to emit a one-line index of a directory, so AI coding agents read a few thousand tokens of metadata up front and only `Read` the files a task actually touches.](../docs/guides/progressive-disclosure.md)

.github/workflows/release.yml

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,13 @@ jobs:
388388
packages-dir: python/dist
389389

390390
release:
391-
needs: [build, vscode]
391+
# `flatpak` joins `build`/`vscode` here so the .flatpak bundle it
392+
# produces is downloaded with the other artifacts and uploaded to
393+
# the draft before it freezes. The bundle is named with the
394+
# `mdsmith-` prefix, so the checksum, SLSA attestation, and cosign
395+
# steps below cover it via the same `mdsmith-*` glob as the raw
396+
# binaries — no release-job changes beyond this dependency.
397+
needs: [build, vscode, flatpak]
392398
runs-on: ubuntu-latest
393399
# See docs/development/release.md for the rationale on `if:`,
394400
# `environment:`, and the OIDC + attestations permission set.
@@ -498,6 +504,95 @@ jobs:
498504
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
499505
run: go run ./cmd/mdsmith-release publish-release
500506

507+
# Build the self-hosted .flatpak bundle. Like `vscode`, this chains
508+
# off `build` (not `release`) and hands its artifact to the `release`
509+
# job, which attaches `mdsmith-x86_64.flatpak` to the draft before it
510+
# freezes — uploading to an immutable, already-published release is
511+
# rejected. The bundle is built from the freshly built x86_64 binary
512+
# via flatpak-builder, so it needs no published download URL. x86_64
513+
# only: flatpak-builder targets the runner's native arch and
514+
# cross-building aarch64 under emulation is not worth it for this
515+
# channel (aarch64 Linux uses the binary, npm, or PyPI channels).
516+
# The job carries no secrets, so it runs without the `release`
517+
# environment gate. See docs/development/release-channels/flatpak.md.
518+
flatpak:
519+
needs: [build]
520+
runs-on: ubuntu-latest
521+
# Bound the heavy steps (apt install + ~hundreds-of-MB Flathub
522+
# runtime pull + flatpak-builder) so a stuck download cannot hold
523+
# the release-gating job to the 6h default.
524+
timeout-minutes: 20
525+
if: *release_repo_trigger_ok
526+
steps:
527+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
528+
with:
529+
persist-credentials: false
530+
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
531+
with:
532+
go-version-file: go.mod
533+
cache: false
534+
- name: Download release artifacts
535+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
536+
with:
537+
path: artifacts
538+
merge-multiple: true
539+
- name: Stage manifest and binaries
540+
# build-flatpak writes the flatpak-builder manifest and copies
541+
# the Linux binaries it references (via local `path:` sources)
542+
# into flatpak-build/, so the bundle builds without a release
543+
# download URL.
544+
run: go run ./cmd/mdsmith-release build-flatpak artifacts flatpak-build
545+
- name: Install flatpak-builder and the freedesktop runtime
546+
run: |
547+
sudo apt-get update
548+
sudo apt-get install -y flatpak flatpak-builder
549+
# Ubuntu 24.04 restricts unprivileged user namespaces via
550+
# AppArmor, which blocks the bubblewrap sandbox that
551+
# flatpak-builder and `flatpak run` rely on. Re-enable it on
552+
# the runner (best-effort: the knob is absent on older
553+
# kernels, where the restriction does not exist).
554+
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
555+
flatpak remote-add --user --if-not-exists \
556+
flathub https://flathub.org/repo/flathub.flatpakrepo
557+
- name: Build the bundle
558+
# flatpak-builder pulls the org.freedesktop 24.08 Platform/SDK
559+
# from flathub, builds the app into a local OSTree repo, and
560+
# build-bundle packs it into a single file. --runtime-repo
561+
# records flathub so `flatpak install ./mdsmith-x86_64.flatpak`
562+
# can offer the runtime if the host lacks it.
563+
# --disable-rofiles-fuse avoids the rofiles-fuse mount, which is
564+
# fragile under the runner's restricted FUSE.
565+
run: |
566+
flatpak-builder --user --install-deps-from=flathub \
567+
--disable-rofiles-fuse --force-clean --repo=flatpak-repo \
568+
flatpak-build-dir flatpak-build/io.github.jeduden.mdsmith.yml
569+
flatpak build-bundle \
570+
--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
571+
flatpak-repo mdsmith-x86_64.flatpak io.github.jeduden.mdsmith
572+
- name: Verify the bundle installs and reports the right version
573+
# No other job exercises this channel (smoke-test runs in
574+
# flatpak-less containers), so confirm the bundle installs and
575+
# `mdsmith version` matches the tag before it ships. A broken
576+
# bundle fails the job — and, since `release` needs it, blocks
577+
# the release rather than shipping a dud asset.
578+
env:
579+
VERSION: ${{ env.VERSION }}
580+
run: |
581+
flatpak install --user -y ./mdsmith-x86_64.flatpak
582+
# Take the last stdout line so a first-run portal/sandbox
583+
# notice cannot break the exact-match check.
584+
got=$(flatpak run io.github.jeduden.mdsmith version | tail -n1)
585+
want="mdsmith ${VERSION}"
586+
if [ "$got" != "$want" ]; then
587+
echo "flatpak bundle version mismatch: got '$got', want '$want'" >&2
588+
exit 1
589+
fi
590+
echo "flatpak bundle: $got"
591+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
592+
with:
593+
name: mdsmith-flatpak-bundle
594+
path: mdsmith-x86_64.flatpak
595+
501596
smoke-test:
502597
# Wait until every channel is on the new version before checking
503598
# — the npm and PyPI registries can take ~60s to surface a fresh

AGENTS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@ row: "- [{summary}]({filename})"
5454
- [The pkg/markdown public package: parse, produce, and its compatibility policy.](docs/development/markdown-library.md)
5555
- [Label-driven merge queue workflow using jeduden/merge-queue-action.](docs/development/merge-queue.md)
5656
- [Rebase, CI monitoring, and review comment resolution.](docs/development/pr-fixup-workflow.md)
57+
- [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)
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
- [Root `@mdsmith/cli` plus one platform-specific subpackage per supported host, all published via OIDC Trusted Publishing.](docs/development/release-channels/npm.md)
5960
- [The same `.vsix` republished to Open VSX so VSCodium, Cursor, Theia, and Gitpod can install it.](docs/development/release-channels/open-vsx.md)
6061
- [One platform-tagged wheel per supported host, published via OIDC Trusted Publishing.](docs/development/release-channels/pypi.md)
6162
- [The mdsmith VS Code extension `.vsix`, published via a long-lived Marketplace publisher PAT.](docs/development/release-channels/visual-studio-marketplace.md)
6263
- [Every GitHub Actions workflow that needs runtime logic invokes the `mdsmith-release` Go CLI rather than carrying inline shell or per-language scripts. This page captures the rule and the subcommands it applies to.](docs/development/release-tooling.md)
63-
- [How a maintainer-dispatched workflow run publishes mdsmith to npm, PyPI, the Visual Studio Marketplace, Open VSX, and GitHub Releases — the workflow structure, the OIDC trusted publishers it relies on, the `release` environment that gates every publishing job, the separate website deploy, and the supply-chain hardening features baked into the pipeline.](docs/development/release.md)
64+
- [How a maintainer-dispatched workflow run publishes mdsmith to npm, PyPI, the Visual Studio Marketplace, Open VSX, a Flatpak bundle, and GitHub Releases — the workflow structure, the OIDC trusted publishers it relies on, the `release` environment that gates every publishing job, the separate website deploy, and the supply-chain hardening features baked into the pipeline.](docs/development/release.md)
6465
- [Rotation cadence and procedure for the long-lived publisher tokens consumed by the release and merge-queue workflows. Each tracked secret has its own file under `secret-rotations/`; the catalog below enumerates them. The scheduled reminder workflow consumes the same files and opens a GitHub issue when any secret is within 30 days of expiry.](docs/development/secret-rotations.md)
6566
- [GitHub fine-grained PAT for the merge-queue action. Plain repo secret — not gated by an environment.](docs/development/secret-rotations/merge-queue-token.md)
6667
- [Open VSX publisher token. Drives the `ovsx publish` step.](docs/development/secret-rotations/ovsx-pat.md)
@@ -95,7 +96,7 @@ row: "- [{summary}]({filename})"
9596
- [When a Markdown file's payload is prose, put it in the body under H2 sections — not in YAML frontmatter. `mdsmith extract` projects body structure into a JSON tree the same way it projects frontmatter, so the file stays editable as Markdown.](docs/guides/extract-markdown-as-data.md)
9697
- [How to declare file kinds, assign files to them, and read the merged rule config that results.](docs/guides/file-kinds.md)
9798
- [User guides for mdsmith directives, structure enforcement, and migration.](docs/guides/index.md)
98-
- [Every channel that ships the mdsmith binary, the VS Code extension, or the Claude Code plugin — npm, PyPI, asdf, mise, the GitHub release, the Visual Studio Marketplace plus Open VSX, and the in-repository Claude Code marketplace — and which channel to pick for which workflow.](docs/guides/install.md)
99+
- [Every channel that ships the mdsmith binary, the VS Code extension, or the Claude Code plugin — npm, PyPI, Homebrew, asdf, mise, a Flatpak bundle, the GitHub release, the Visual Studio Marketplace plus Open VSX, and the in-repository Claude Code marketplace — and which channel to pick for which workflow.](docs/guides/install.md)
99100
- [Trade-offs and threshold guidance for readability, structure, length, and token budgets.](docs/guides/metrics-tradeoffs.md)
100101
- [Move a project from markdownlint-cli or markdownlint-cli2 to mdsmith — the rule mapping, the config rewrite, and the markdownlint-to-mdsmith rule correspondence.](docs/guides/migrate-from-markdownlint.md)
101102
- [Use `<?catalog?>` with a per-file `summary` front matter field to emit a one-line index of a directory, so AI coding agents read a few thousand tokens of metadata up front and only `Read` the files a task actually touches.](docs/guides/progressive-disclosure.md)

0 commit comments

Comments
 (0)