Skip to content

Commit 0b2f151

Browse files
committed
feat: install mergify-cli from prebuilt release binary
Replace the Python + uv install path (`uv tool install mergify-cli`) with the mergify-cli prebuilt binary, installed via the CLI's own `install.sh` installer pinned to the release being installed. Why delegate to install.sh rather than re-implement the download/verify: - install.sh owns platform detection, asset naming, and SHA256SUMS verification, so the action doesn't duplicate that logic or have to track it when the asset naming changes (it already changed once between releases). - It stays reproducible: we fetch install.sh pinned to the exact release tag (not `main`), and resolve `latest` ourselves via the github.com `/releases/latest` redirect so we can pass MERGIFY_VERSION explicitly — the installer never calls api.github.com. Details: - Resolve the version, fetch `install.sh` at that tag, run it with MERGIFY_VERSION + MERGIFY_INSTALL_DIR, add the dir to $GITHUB_PATH. - The `mergify_cli_version` output is read back from `mergify --version` (the binary reports its real version), accurate for both pinned and `latest`. - Default bumped to 2026.6.16.1, the first release with prebuilt binaries + install.sh under the canonical versioned asset naming. - Renovate datasource moved pypi -> github-releases (Mergifyio/mergify-cli, pep440). - CI test-install is a matrix over the target triples install.sh supports (linux/macos, x86_64 + aarch64). install.sh currently supports Linux and macOS only; Windows is picked up automatically once install.sh ships a Windows path. BREAKING CHANGE: the `python_version` input is removed (no Python is used) and the action no longer provisions Python/uv on PATH as a side effect. Fixes MRGFY-7660 Change-Id: If70ad03ddf01ec196f051fef6489b68904d02b20
1 parent 2440cd0 commit 0b2f151

4 files changed

Lines changed: 78 additions & 45 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,39 @@ jobs:
6161
6262
test-install:
6363
timeout-minutes: 5
64-
runs-on: ubuntu-24.04
64+
# One runner per target triple install.sh supports, so every detection +
65+
# extraction path is exercised: linux+macos on both x86_64 and aarch64.
66+
# (Windows is added once install.sh ships a Windows path.)
67+
strategy:
68+
fail-fast: false
69+
matrix:
70+
os:
71+
- ubuntu-24.04 # x86_64-unknown-linux-gnu
72+
- ubuntu-24.04-arm # aarch64-unknown-linux-gnu
73+
- macos-15-intel # x86_64-apple-darwin
74+
- macos-15 # aarch64-apple-darwin
75+
runs-on: ${{ matrix.os }}
76+
defaults:
77+
run:
78+
shell: bash
6579
steps:
6680
- name: Checkout 🛎️
6781
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
6882

6983
- name: Install pinned mergify-cli
7084
id: pinned
7185
uses: ./
86+
with:
87+
mergify_cli_version: 2026.6.16.1
7288

7389
- name: Assert pinned install
7490
env:
7591
VERSION: ${{ steps.pinned.outputs.mergify_cli_version }}
7692
run: |
77-
test -n "$VERSION"
78-
mergify --version
93+
# Compare against the literal requested version (not the action's own
94+
# readback), so a regression that installs the wrong version fails CI.
95+
test "$VERSION" = "2026.6.16.1"
96+
test "$(mergify --version | awk '{print $NF}')" = "2026.6.16.1"
7997
8098
- name: Install latest mergify-cli
8199
id: latest
@@ -88,7 +106,7 @@ jobs:
88106
VERSION: ${{ steps.latest.outputs.mergify_cli_version }}
89107
run: |
90108
test -n "$VERSION"
91-
mergify --version
109+
test "$(mergify --version | awk '{print $NF}')" = "$VERSION"
92110
93111
all-greens:
94112
if: ${{ !cancelled() }}

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# setup-cli
22

3-
GitHub Action to install the [Mergify CLI](https://pypi.org/project/mergify-cli/)
3+
GitHub Action to install the [Mergify CLI](https://github.com/Mergifyio/mergify-cli)
44
(`mergify-cli`) with version pinning and Renovate autoupdate.
55

6-
It sets up Python, installs `uv`, then installs `mergify-cli` (pinned by default,
7-
`latest` supported) and exposes the resolved version as an output.
6+
It installs the prebuilt `mergify` binary via the mergify-cli `install.sh`
7+
installer (pinned to the release being installed), which downloads the binary
8+
from the GitHub release and verifies it against the release `SHA256SUMS`. The
9+
action then puts it on `PATH` and exposes the installed version as an output.
10+
Pinned by default, `latest` supported. No Python or toolchain is required;
11+
Linux and macOS are supported.
812

913
More information on https://mergify.com
1014

@@ -35,13 +39,12 @@ Pin a specific `mergify-cli` version, or install the latest one:
3539

3640
| Input | Type | Required | Default | Description |
3741
| --- | --- | --- | --- | --- |
38-
| `mergify_cli_version` | string | false | `2026.6.8.1` | Version of mergify-cli to install. Use `latest` to install the latest released version without pinning. |
39-
| `python_version` | string | false | `3.14` | Python version to set up for the install (passed to actions/setup-python). |
42+
| `mergify_cli_version` | string | false | `2026.6.16.1` | Version of mergify-cli to install. Use `latest` to install the latest released version without pinning. |
4043

4144
<!-- AUTO-DOC-INPUT:END -->
4245

4346
## Outputs
4447

4548
| Output | Description |
4649
| --- | --- |
47-
| `mergify_cli_version` | The `mergify-cli` version that was installed. Resolved from the installed package metadata, so it reflects the real version even when `latest` or an empty input was requested. |
50+
| `mergify_cli_version` | The `mergify-cli` version that was installed. Read back from the installed binary, so it reflects the real version even when `latest` or an empty input was requested. |

action.yml

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Setup Mergify CLI
2-
description: Install the Mergify CLI (mergify-cli) with version pinning.
2+
description: Install the Mergify CLI (mergify-cli) prebuilt binary with version pinning.
33
author: Mergify
44
branding:
55
icon: terminal
@@ -9,48 +9,59 @@ inputs:
99
description: |
1010
Version of mergify-cli to install. Use `latest` to install the latest
1111
released version without pinning.
12-
# renovate: datasource=pypi depName=mergify-cli
13-
default: 2026.6.8.1
14-
python_version:
15-
description: Python version to set up for the install (passed to actions/setup-python).
16-
default: "3.14"
12+
# renovate: datasource=github-releases depName=Mergifyio/mergify-cli versioning=pep440
13+
default: 2026.6.16.1
1714
outputs:
1815
mergify_cli_version:
1916
description: |
20-
The mergify-cli version that was installed. Resolved from the installed
21-
package metadata, so it reflects the real version even when `latest` or an
22-
empty input was requested.
17+
The mergify-cli version that was installed. Read back from the installed
18+
binary, so it reflects the real version even when `latest` or an empty
19+
input was requested.
2320
value: ${{ steps.install.outputs.mergify_cli_version }}
2421
runs:
2522
using: composite
2623
steps:
27-
- name: Setup Python 🔧
28-
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
29-
with:
30-
python-version: ${{ inputs.python_version }}
31-
32-
- name: Install uv
33-
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
34-
with:
35-
# mergify is too small to benefit + there is no version lock (so no cache key either)
36-
enable-cache: false
37-
3824
- name: Install mergify-cli
3925
id: install
4026
shell: bash
4127
env:
4228
MERGIFY_CLI_VERSION: ${{ inputs.mergify_cli_version }}
4329
run: |
44-
if [ -z "$MERGIFY_CLI_VERSION" ] || [ "$MERGIFY_CLI_VERSION" = "latest" ]; then
45-
# --upgrade implies --refresh, so uv re-resolves against PyPI and
46-
# installs the newest release even on persistent self-hosted runners
47-
# where an older mergify-cli is already cached.
48-
uv tool install --upgrade mergify-cli
30+
set -euo pipefail
31+
32+
REPO="Mergifyio/mergify-cli"
33+
34+
die() { echo "::error::$1" >&2; exit 1; }
35+
36+
# Resolve `latest`/empty to a concrete tag by following the
37+
# `/releases/latest` redirect (plain github.com, no API token, no
38+
# api.github.com rate limit), so we can pin install.sh to that exact
39+
# release and hand the version to it explicitly.
40+
if [ -z "${MERGIFY_CLI_VERSION}" ] || [ "${MERGIFY_CLI_VERSION}" = "latest" ]; then
41+
effective=$(curl -fsSL -o /dev/null -w '%{url_effective}' "https://github.com/${REPO}/releases/latest") \
42+
|| die "could not reach github.com to resolve the latest mergify-cli release"
43+
version=${effective##*/tag/}
44+
[ -n "${version}" ] && [ "${version}" != "${effective}" ] || die "could not resolve latest mergify-cli release from ${effective}"
4945
else
50-
uv tool install "mergify-cli==$MERGIFY_CLI_VERSION"
46+
version=${MERGIFY_CLI_VERSION}
5147
fi
52-
mergify --version
53-
# `mergify --version` may print a placeholder while versioning becomes
54-
# Rust-native, so read the resolved version from the package metadata.
55-
installed=$(uv tool list | awk '/^mergify-cli /{print $2}' | sed 's/^v//')
56-
echo "mergify_cli_version=$installed" >> "$GITHUB_OUTPUT"
48+
49+
bindir="${RUNNER_TEMP}/mergify-cli-bin"
50+
51+
# Install via the CLI's own installer, pinned to the release being
52+
# installed: it owns platform detection, asset naming, and SHA256SUMS
53+
# verification, so we don't duplicate (or have to track) any of that.
54+
# MERGIFY_VERSION is passed explicitly so the installer never calls
55+
# api.github.com. install.sh supports Linux and macOS only.
56+
tmp=$(mktemp -d)
57+
trap 'rm -rf "${tmp}"' EXIT
58+
curl -fsSL "https://raw.githubusercontent.com/${REPO}/${version}/install.sh" -o "${tmp}/install.sh" \
59+
|| die "failed to fetch install.sh for ${version} — does this release ship prebuilt binaries?"
60+
MERGIFY_VERSION="${version}" MERGIFY_INSTALL_DIR="${bindir}" sh "${tmp}/install.sh"
61+
62+
# Expose the binary to later steps and read the version back from it
63+
# (the binary reports its real version) for the action output.
64+
echo "${bindir}" >> "${GITHUB_PATH}"
65+
installed=$("${bindir}/mergify" --version | awk '{print $NF}')
66+
[ -n "${installed}" ] || die "could not read installed mergify-cli version"
67+
echo "mergify_cli_version=${installed}" >> "${GITHUB_OUTPUT}"

renovate.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"lockFileMaintenance": { "enabled": true },
1212
"packageRules": [
1313
{
14-
"matchDatasources": ["pypi"],
15-
"matchPackageNames": ["mergify-cli"],
14+
"matchDatasources": ["github-releases"],
15+
"matchPackageNames": ["Mergifyio/mergify-cli"],
1616
"minimumReleaseAge": "2 days"
1717
},
1818
{
@@ -40,8 +40,9 @@
4040
"matchStrings": [
4141
"\\| `mergify_cli_version` \\| string \\| \\w+ \\| `(?<currentValue>[^`]+)` \\|"
4242
],
43-
"datasourceTemplate": "pypi",
44-
"depNameTemplate": "mergify-cli"
43+
"datasourceTemplate": "github-releases",
44+
"depNameTemplate": "Mergifyio/mergify-cli",
45+
"versioningTemplate": "pep440"
4546
},
4647
{
4748
"description": "Bump the self-referenced action version pinned in the README usage example on each new setup-cli release.",

0 commit comments

Comments
 (0)