Release sss_code/v0.3.1 #66
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| run-name: Release ${{ github.event.inputs.tag || github.ref_name }} | |
| # Two parallel tag streams trigger this workflow: | |
| # sss_cli/v0.2.1 → releases the `sss` binary (sss_cli) | |
| # sss_code/v0.3.0 → releases the `sss_code` binary | |
| # | |
| # Library crates (sss_core, sss_lib, sss_ocr, sss_capture, sss_capture_ui) | |
| # have `tag = false` in their per-crate release metadata so cargo-release | |
| # bumps their version + commit but never tags them — only the two binary | |
| # crates fan into this workflow. | |
| # | |
| # `workflow_dispatch` lets you force a release from a tag too. | |
| on: | |
| push: | |
| tags: | |
| - "sss_cli/v*" | |
| - "sss_code/v*" | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Tag to release (e.g. sss_cli/v0.2.1 or sss_code/v0.3.0)." | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| # Resolve which binary we're releasing + which version, once for all | |
| # downstream jobs to consume via `needs.plan.outputs.*`. | |
| plan: | |
| name: Plan release | |
| runs-on: ubuntu-latest | |
| outputs: | |
| tag: ${{ steps.plan.outputs.tag }} | |
| binary: ${{ steps.plan.outputs.binary }} | |
| version: ${{ steps.plan.outputs.version }} | |
| release_name: ${{ steps.plan.outputs.release_name }} | |
| crate_dir: ${{ steps.plan.outputs.crate_dir }} | |
| tag_pattern: ${{ steps.plan.outputs.tag_pattern }} | |
| cliff_paths: ${{ steps.plan.outputs.cliff_paths }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.inputs.tag || github.ref }} | |
| fetch-depth: 0 | |
| - name: Resolve target | |
| id: plan | |
| run: | | |
| tag="${{ github.event.inputs.tag || github.ref_name }}" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| case "$tag" in | |
| sss_code/v*) | |
| binary=sss_code | |
| version="${tag#sss_code/v}" | |
| crate_dir=sss_code | |
| tag_pattern='sss_code/v[0-9]+\.[0-9]+\.[0-9]+' | |
| # sss_code depends on sss_lib (rendering pipeline) and | |
| # sss_core (shared primitives). Changes in either land in | |
| # the same binary, so include them in the changelog. | |
| cliff_paths='--include-path crates/sss_code/** --include-path crates/sss_lib/** --include-path crates/sss_core/**' | |
| crate=crates/sss_code/Cargo.toml ;; | |
| sss_cli/v*) | |
| binary=sss | |
| version="${tag#sss_cli/v}" | |
| crate_dir=sss_cli | |
| tag_pattern='sss_cli/v[0-9]+\.[0-9]+\.[0-9]+' | |
| # sss_cli pulls every workspace crate (sss_lib for render, | |
| # sss_core primitives, sss_capture + sss_capture_ui for the | |
| # selector/annotator, sss_ocr for text recognition). All of | |
| # them ship inside the `sss` binary, so all are in scope. | |
| cliff_paths='--include-path crates/sss_cli/** --include-path crates/sss_lib/** --include-path crates/sss_core/** --include-path crates/sss_capture/** --include-path crates/sss_capture_ui/** --include-path crates/sss_ocr/**' | |
| crate=crates/sss_cli/Cargo.toml ;; | |
| *) | |
| echo "::error::tag '$tag' does not match sss_cli/v* or sss_code/v*" | |
| exit 1 ;; | |
| esac | |
| echo "binary=$binary" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "release_name=$binary v$version" >> "$GITHUB_OUTPUT" | |
| echo "crate_dir=$crate_dir" >> "$GITHUB_OUTPUT" | |
| echo "tag_pattern=$tag_pattern" >> "$GITHUB_OUTPUT" | |
| echo "cliff_paths=$cliff_paths" >> "$GITHUB_OUTPUT" | |
| crate_ver=$(awk -F\" '/^version = /{print $2; exit}' "$crate") | |
| if [ "$crate_ver" != "$version" ]; then | |
| echo "::error::$crate version ($crate_ver) does not match tag ($version)" | |
| exit 1 | |
| fi | |
| # Per-runner slice builds. Each runner only emits what it can produce | |
| # natively (or via pkgsCross on the linux host); the publish job stitches | |
| # every artifact into a single release. | |
| # | |
| # `variant` axis: every `sss` (sss_cli) tag releases TWO sets of bundles | |
| # in parallel — the full build (default features, ships libonnxruntime + | |
| # CUDA stack inside the bundle) and a `no-ocr` build (`--no-default-features`, | |
| # no OCR code, distro packages list `onnxruntime` as a recommendation). | |
| # `sss_code` only ships in one flavour; the matrix is filtered below. | |
| bundles: | |
| name: Build bundles (${{ matrix.slice.label }} ${{ matrix.variant }}) | |
| needs: plan | |
| runs-on: ${{ matrix.slice.runner }} | |
| timeout-minutes: 90 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| slice: | |
| - label: linux-x86_64 | |
| runner: ubuntu-latest | |
| slice: linux-x86_64 | |
| - label: linux-aarch64 | |
| runner: ubuntu-24.04-arm | |
| slice: linux-aarch64 | |
| - label: macos-aarch64 | |
| runner: macos-14 | |
| slice: darwin-aarch64 | |
| variant: [system, nvidia, rocm, noocr] | |
| # Static excludes drop combinations that cannot produce any | |
| # artifact, so the matrix doesn't spawn a runner just to no-op. | |
| # Per-variant slice restrictions: | |
| # - any slice × `nvidia` on macOS → no CUDA stack on Apple | |
| # - any slice × `rocm` except linux-x86_64 → ROCm only on Linux-x86_64 | |
| # `sss_code` × {nvidia, rocm, noocr} can't be expressed here (the | |
| # binary name resolves only at job time from `needs.plan.outputs`); | |
| # those are still gated via the `Plan slice` step below. | |
| # x86_64-darwin slice dropped: nixpkgs deprecating it (26.05 is | |
| # the last supported), GitHub macos-13 runners queue indefinitely | |
| # on free-tier quotas. aarch64-darwin covers modern Mac users. | |
| exclude: | |
| - slice: | |
| label: macos-aarch64 | |
| runner: macos-14 | |
| slice: darwin-aarch64 | |
| variant: nvidia | |
| - slice: | |
| label: macos-aarch64 | |
| runner: macos-14 | |
| slice: darwin-aarch64 | |
| variant: rocm | |
| - slice: | |
| label: linux-aarch64 | |
| runner: ubuntu-24.04-arm | |
| slice: linux-aarch64 | |
| variant: rocm | |
| steps: | |
| - name: Plan slice | |
| id: pin | |
| shell: bash | |
| run: | | |
| # The matrix `exclude:` already prunes combinations that can't | |
| # produce any artifact. This step handles the dynamic gate: if | |
| # the tag belongs to `sss_code`, the only eligible variant is | |
| # `system` — `nvidia`/`rocm`/`noocr` are sss-only. | |
| eligible=true | |
| variant="${{ matrix.variant }}" | |
| binary="${{ needs.plan.outputs.binary }}" | |
| slice="${{ matrix.slice.slice }}" | |
| if [ "$binary" != "sss" ] && [ "$variant" != "system" ]; then | |
| eligible=false | |
| fi | |
| echo "eligible=$eligible" >> "$GITHUB_OUTPUT" | |
| echo "Plan: variant=$variant binary=$binary slice=$slice → eligible=$eligible" | |
| - name: Checkout | |
| if: steps.pin.outputs.eligible == 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.plan.outputs.tag }} | |
| fetch-depth: 0 | |
| - name: Install Nix | |
| if: steps.pin.outputs.eligible == 'true' | |
| uses: DeterminateSystems/nix-installer-action@main | |
| with: | |
| extra-conf: | | |
| experimental-features = nix-command flakes | |
| accept-flake-config = true | |
| # Attic-backed binary cache hosted at cache.sergioribera.rs (`main`). | |
| # The action wires the cache up as a substituter (so the build can pull | |
| # nixpkgs + workspace artifacts that were already pushed) and uploads | |
| # any new store paths created during the job in its post step. | |
| - name: Attic cache | |
| if: steps.pin.outputs.eligible == 'true' | |
| uses: ryanccn/attic-action@v0 | |
| with: | |
| endpoint: https://cache.sergioribera.rs | |
| cache: main | |
| token: ${{ secrets.ATTIC_TOKEN }} | |
| - name: Build release slice | |
| if: steps.pin.outputs.eligible == 'true' | |
| run: | | |
| # `system` variant for `sss` maps to the bare `release-sss` | |
| # flake output; all other variants suffix the variant name. | |
| # `sss_code` only ever uses the bare `release-sss_code` output. | |
| attr="release-${{ needs.plan.outputs.binary }}" | |
| if [ "${{ needs.plan.outputs.binary }}" = "sss" ] && [ "${{ matrix.variant }}" != "system" ]; then | |
| attr="release-sss-${{ matrix.variant }}" | |
| fi | |
| # `--fallback` rebuilds from source when a substituter starts | |
| # serving a NAR but the stream breaks mid-transfer (we hit | |
| # HTTP/2 framing errors against attic intermittently). Without | |
| # this the build aborts even though Nix could just re-derive | |
| # the path locally. | |
| nix build ".#$attr" -L --fallback --print-out-paths | |
| - name: Stage artifacts | |
| if: steps.pin.outputs.eligible == 'true' | |
| run: | | |
| mkdir -p dist | |
| # `cp -RL` portable across GNU + BSD. nix store paths are 555 — | |
| # `chmod -R u+w` makes the staged copy writable so later steps | |
| # (upload-artifact, mv) don't hit EACCES on macOS. | |
| cp -RL result/* dist/ | |
| chmod -R u+w dist/ | |
| # Drop bundler-generated install scaffolding: install.sh comes | |
| # from `scripts/install.sh` (uploaded by publish), INSTALL.md is | |
| # replaced by an inline install snippet in the release body. | |
| # SHA256SUMS per slice still gets renamed so the publish job | |
| # can stitch a unified one without collisions. | |
| tag="${{ matrix.slice.slice }}-${{ matrix.variant }}" | |
| rm -f dist/INSTALL.md dist/install.sh dist/install.ps1 | |
| mv dist/SHA256SUMS "dist/SHA256SUMS-${tag}" 2>/dev/null || true | |
| ls -la dist | |
| - name: Upload slice | |
| if: steps.pin.outputs.eligible == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bundles-${{ matrix.slice.slice }}-${{ matrix.variant }} | |
| path: dist/ | |
| if-no-files-found: error | |
| retention-days: 1 | |
| publish: | |
| name: Publish GitHub Release | |
| needs: [plan, bundles] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| outputs: | |
| has_aur: ${{ steps.aur_detect.outputs.has_aur }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.plan.outputs.tag }} | |
| fetch-depth: 0 | |
| # Download each (slice, variant) artifact into its own subdir so the | |
| # variant-specific `aur/` layouts don't clobber each other (their | |
| # filenames inside `aur/` are the same `PKGBUILD` / `.SRCINFO`, | |
| # only the content differs). Then flatten the non-AUR pieces into | |
| # `dist/` — variant disambiguation lives in the bundle filename | |
| # (`sss-*` vs `sss-no-ocr-*`) so no collisions there. | |
| - name: Download all bundles | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: bundles-* | |
| path: bundles_raw | |
| - name: Flatten non-AUR artifacts into dist/ | |
| run: | | |
| mkdir -p dist aur_system aur_nvidia aur_rocm aur_noocr | |
| shopt -s nullglob | |
| for sub in bundles_raw/*/; do | |
| slice_dir="${sub%/}" | |
| name=$(basename "$slice_dir") | |
| variant=system | |
| case "$name" in | |
| *-system) variant=system ;; | |
| *-nvidia) variant=nvidia ;; | |
| *-rocm) variant=rocm ;; | |
| *-noocr) variant=noocr ;; | |
| esac | |
| # Pull the AUR source layout aside per variant so the four | |
| # PKGBUILD/.SRCINFO sets don't clobber each other (filenames | |
| # are identical inside `aur/`, only content differs). | |
| if [ -d "$slice_dir/aur" ]; then | |
| cp -r "$slice_dir/aur/." "aur_${variant}/" || true | |
| rm -rf "$slice_dir/aur" | |
| fi | |
| # Everything else flattens straight in. Brew formulas (.rb) | |
| # stay per-slice because the homebrew job needs to merge | |
| # them by arch — we copy them into dist/ keyed by source | |
| # subdir name. | |
| cp -r "$slice_dir/." "dist/" | |
| done | |
| ls -la dist | head -50 | |
| - name: Generate unified SHA256SUMS | |
| working-directory: dist | |
| run: | | |
| rm -f SHA256SUMS-* | |
| find . -maxdepth 1 -type f \ | |
| ! -name 'SHA256SUMS*' \ | |
| ! -name 'INSTALL-*.md' \ | |
| ! -name 'install-*.sh' \ | |
| ! -name 'install-*.ps1' \ | |
| -printf '%P\n' \ | |
| | LC_ALL=C sort \ | |
| | xargs sha256sum -- > SHA256SUMS | |
| - name: Stage install.sh | |
| working-directory: dist | |
| run: | | |
| # install.sh ships as a tracked script in `scripts/install.sh` | |
| # rather than the bundler-generated per-slice one. Reasons: the | |
| # bundler emits one script per slice with hardcoded `NAME=` and | |
| # duplicate `file_for()` cases that make variant selection | |
| # impossible. The custom script resolves variant + version via | |
| # flags and the GH releases API. | |
| cp ../scripts/install.sh install.sh | |
| chmod +x install.sh | |
| - name: Pack AUR layouts for downstream workflow | |
| id: aur_detect | |
| run: | | |
| # The archlinux format emits the AUR layout in `aur/` next to | |
| # the .pkg.tar.zst. The AUR push workflow expects one tarball | |
| # per AUR package. For `sss` we ship four: `sss-bin`, | |
| # `sss-nvidia-bin`, `sss-rocm-bin`, `sss-noocr-bin`. | |
| # `sss_code` only ships one: `sss_code-bin`. | |
| ver="${{ needs.plan.outputs.version }}" | |
| binary="${{ needs.plan.outputs.binary }}" | |
| has_any=false | |
| pack() { | |
| local dir=$1 pkg=$2 | |
| if [ -d "$dir" ] && [ -n "$(ls -A "$dir")" ]; then | |
| # The archlinux format emits the AUR source tarball | |
| # (`<pkg>-<ver>-<arch>.tar.gz`) inside `aur/` alongside | |
| # PKGBUILD. PKGBUILD's `source=()` points to it as a | |
| # release asset URL, so we lift it into `dist/` to be | |
| # uploaded directly — otherwise makepkg/updpkgsums 404s. | |
| for src_tar in "$dir"/${pkg}-*.tar.gz; do | |
| [ -f "$src_tar" ] || continue | |
| cp "$src_tar" "dist/$(basename "$src_tar")" | |
| done | |
| tar czf "dist/${pkg}-${ver}-aur.tar.gz" -C "$dir" . | |
| has_any=true | |
| fi | |
| } | |
| if [ "$binary" = "sss" ]; then | |
| pack aur_system sss-bin | |
| pack aur_nvidia sss-nvidia-bin | |
| pack aur_rocm sss-rocm-bin | |
| pack aur_noocr sss-noocr-bin | |
| elif [ "$binary" = "sss_code" ]; then | |
| pack aur_system sss_code-bin | |
| fi | |
| echo "has_aur=$has_any" >> "$GITHUB_OUTPUT" | |
| - name: Generate changelog with git-cliff | |
| uses: orhun/git-cliff-action@v4 | |
| id: cliff | |
| with: | |
| config: cliff.toml | |
| # Scope the changelog to the binary being released: | |
| # * `--tag-pattern` restricts the "previous tag" walk to the | |
| # same release stream so a sss_cli release doesn't reach | |
| # back to the most recent sss_code tag (or vice versa) and | |
| # drag every workspace commit since then into the body. | |
| # * `--include-path` keeps only commits touching the binary's | |
| # own crate directory. Workspace-wide changes (shared libs, | |
| # CI infra, docs) intentionally don't land here — they show | |
| # up in whichever binary they actually affected. | |
| # * `--tag` is explicit instead of `--current`: cargo-release | |
| # can land cross-tag commits at the same SHA, so trusting | |
| # the implicit HEAD lookup mis-attributes the release. | |
| args: > | |
| --latest | |
| --tag-pattern '${{ needs.plan.outputs.tag_pattern }}' | |
| ${{ needs.plan.outputs.cliff_paths }} | |
| --strip header | |
| env: | |
| OUTPUT: CHANGELOG.md | |
| - name: Assemble release body | |
| run: | | |
| binary="${{ needs.plan.outputs.binary }}" | |
| tag="${{ needs.plan.outputs.tag }}" | |
| base="https://github.com/${{ github.repository }}/releases/download/${tag}" | |
| { | |
| cat CHANGELOG.md 2>/dev/null || echo "_(no changelog generated)_" | |
| echo | |
| echo "## Install" | |
| echo | |
| echo '```sh' | |
| if [ "$binary" = "sss_code" ]; then | |
| echo "curl -fsSL $base/install.sh | sh -s -- --binary sss_code" | |
| else | |
| echo "curl -fsSL $base/install.sh | sh" | |
| echo "# variants: --variant nvidia | --variant rocm | --variant noocr" | |
| fi | |
| echo '```' | |
| echo | |
| printf '%s\n' 'Detects distro, picks `.deb` / `.rpm` / `.pkg.tar.zst` / tarball, verifies SHA256. Flags: `--version vX.Y.Z`, `--format FMT`, `--dir DIR`, `--uninstall`. Manual bundles + checksums in the release assets below.' | |
| } > RELEASE_BODY.md | |
| echo "--- release body preview ---" | |
| head -120 RELEASE_BODY.md | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.plan.outputs.tag }} | |
| name: ${{ needs.plan.outputs.release_name }} | |
| draft: false | |
| prerelease: ${{ contains(needs.plan.outputs.tag, '-') }} | |
| body_path: RELEASE_BODY.md | |
| # The globs below cover every format nix-bundle-app may emit, | |
| # but most releases only produce a subset (sss_code skips deb | |
| # variants on some slices, darwin doesn't produce .deb / .rpm, | |
| # etc). `fail_on_unmatched_files: false` lets the publish | |
| # succeed against whichever shape this release happened to | |
| # produce; the SHA256SUMS still pins the full asset list. | |
| fail_on_unmatched_files: false | |
| # Exclude the `aur/` subdir from the release upload — it's the | |
| # source layout for the AUR repo, not a user-installable artifact. | |
| # AppImage intentionally absent: dropped in release.nix because | |
| # the binary expects a distro-installed libonnxruntime which | |
| # breaks AppImage's portability promise. Listing the glob with | |
| # `fail_on_unmatched_files: true` would abort the publish job. | |
| files: | | |
| dist/*.deb | |
| dist/*.rpm | |
| dist/*.pkg.tar.zst | |
| dist/*.tar.gz | |
| dist/*.tar.zst | |
| dist/*.dmg | |
| dist/*.pkg | |
| dist/*.rb | |
| dist/*-aur.tar.gz | |
| dist/SHA256SUMS | |
| dist/install.sh | |
| # Pushes Homebrew formula files to SergioRibera/homebrew-tap. Triggered | |
| # by the AUR push workflow indirectly (both react to a successful | |
| # Release run via workflow_run). AUR runs in aur.yml, brew runs here so | |
| # the secrets stay isolated per ecosystem. | |
| homebrew: | |
| name: Publish to Homebrew tap | |
| needs: [plan, publish] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| # Keep per-slice subdirs — each runner's .rb has the SAME filename | |
| # (`sss.rb` / `sss_code.rb`) but different content per arch, so | |
| # `merge-multiple: true` would silently lose one arch. | |
| - name: Download brew formulas | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: bundles-* | |
| path: dist | |
| # nix-bundle-app emits one single-arch formula per (binary, target), | |
| # and its `url` field is the bare `meta.downloadUrl` (a directory). | |
| # We merge per-arch into a universal `on_macos { on_arm / on_intel }` | |
| # formula AND rewrite the url to the actual tarball asset for that | |
| # arch. Output filename + class are remapped per binary so the tap | |
| # keeps the legacy `sss_cli.rb` / `sss_code.rb` names (cli's crate | |
| # is `sss_cli` but its binary is `sss` — Homebrew users typed | |
| # `brew install sergioribera/tap/sss_cli` historically). | |
| - name: Merge per-arch formulas into universal | |
| id: merge | |
| run: | | |
| python3 - <<'PY' | |
| import collections, glob, os, pathlib, re | |
| # internal-name (from meta.name) -> (formula filename stem, | |
| # ruby class, installed binary). The brew test stanza needs the | |
| # ACTUAL binary that lands in $bin, not the formula stem. | |
| # Only the `system` and `noocr` variants ship on macOS — nvidia | |
| # and rocm are Linux-only and never produce a brew formula. | |
| rename = { | |
| "sss": ("sss_cli", "SssCli", "sss"), | |
| "sss-noocr": ("sss_cli_noocr", "SssCliNoocr", "sss"), | |
| "sss_code": ("sss_code", "SssCode", "sss_code"), | |
| } | |
| slices = collections.defaultdict(dict) # name -> {arch: (url, sha)} | |
| fields = {} # name -> shared metadata | |
| # Slice dir name is `bundles-darwin-<arch>-<variant>`. We only | |
| # care about <arch> for the merge axis — the formula stem | |
| # already disambiguates the variant via `meta.name`. | |
| for slice_dir in sorted(glob.glob("dist/bundles-darwin-*")): | |
| base = pathlib.Path(slice_dir).name | |
| arch = "arm" if "aarch64" in base else "intel" | |
| os_label = "darwin" | |
| for rb in glob.glob(f"{slice_dir}/*.rb"): | |
| text = pathlib.Path(rb).read_text() | |
| name = pathlib.Path(rb).stem | |
| base_url = re.search(r'url\s+"([^"]+)"', text).group(1) | |
| sha = re.search(r'sha256\s+"([^"]+)"', text).group(1) | |
| version = re.search(r'version\s+"([^"]+)"', text).group(1) | |
| # Construct the actual tarball asset URL. | |
| asset_arch = "x86_64" if arch == "intel" else "aarch64" | |
| tarball = f"{name}-{version}-{asset_arch}-{os_label}.tar.gz" | |
| url = base_url.rstrip("/") + "/" + tarball | |
| slices[name][arch] = (url, sha) | |
| fields.setdefault(name, { | |
| "desc": re.search(r'desc\s+"([^"]+)"', text).group(1), | |
| "homepage": re.search(r'homepage\s+"([^"]+)"', text).group(1), | |
| "version": version, | |
| "license": re.search(r'license\s+"([^"]+)"', text).group(1), | |
| }) | |
| if not slices: | |
| print("::notice::no darwin .rb formulas to publish") | |
| with open(os.environ["GITHUB_OUTPUT"], "a") as fh: | |
| fh.write("skip=true\n") | |
| raise SystemExit(0) | |
| os.makedirs("formulas", exist_ok=True) | |
| for name, f in fields.items(): | |
| file_stem, klass, binary = rename.get( | |
| name, (name, name[:1].upper() + name[1:], name) | |
| ) | |
| arches = slices[name] | |
| parts = [ | |
| f"class {klass} < Formula", | |
| f' desc "{f["desc"]}"', | |
| f' homepage "{f["homepage"]}"', | |
| f' version "{f["version"]}"', | |
| f' license "{f["license"]}"', | |
| "", | |
| " on_macos do", | |
| ] | |
| for label, key in (("on_arm", "arm"), ("on_intel", "intel")): | |
| if key in arches: | |
| url, sha = arches[key] | |
| parts += [ | |
| f" {label} do", | |
| f' url "{url}"', | |
| f' sha256 "{sha}"', | |
| " end", | |
| ] | |
| parts += [ | |
| " end", | |
| "", | |
| " def install", | |
| ' bin.install Dir["bin/*"]', | |
| ' lib.install Dir["lib/*"] if Dir.exist?("lib")', | |
| ' share.install Dir["share/*"] if Dir.exist?("share")', | |
| " end", | |
| "", | |
| " test do", | |
| f' system "#{{bin}}/{binary}", "--version"', | |
| " end", | |
| "end", | |
| "", | |
| ] | |
| pathlib.Path(f"formulas/{file_stem}.rb").write_text("\n".join(parts)) | |
| print(f"wrote formulas/{file_stem}.rb ({', '.join(arches)})") | |
| PY | |
| ls -la formulas || true | |
| - name: Checkout homebrew-tap | |
| if: steps.merge.outputs.skip != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: SergioRibera/homebrew-tap | |
| token: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| path: tap | |
| - name: Commit + push formulas | |
| if: steps.merge.outputs.skip != 'true' | |
| working-directory: tap | |
| env: | |
| BINARY: ${{ needs.plan.outputs.binary }} | |
| VERSION: ${{ needs.plan.outputs.version }} | |
| run: | | |
| mkdir -p Formula | |
| cp -f ../formulas/*.rb Formula/ | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add Formula/*.rb | |
| if git diff --cached --quiet; then | |
| echo "no formula changes" | |
| exit 0 | |
| fi | |
| git commit -m "$BINARY $VERSION" | |
| git push |