Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,37 @@ changes release inputs, including a workspace member's `pyproject.toml` or a sec
formatting job runs `prek`; the writer checks patch paths and modes. Its `changed` output is `true` only when the
refresh produces a patch. Neither mode pushes a branch or requests a write token.

## Refresh a pinned mise binary

`refresh-mise-pin` updates one named `jdx/mise-action` step in a release workflow. It selects the newest stable mise
GitHub Release whose publication and Linux executable upload are at least seven days old. The executable must also be
unchanged for seven days. The Action installs that version through the pinned mise Action and compares the executable
with the release asset digest. The mise Action verifies the download against mise's minisign-signed checksum file. The
refresh Action fails if the named step is missing or duplicated, its version or digest is not literal, or the installed
binary differs from the selected release. It changes only that step's `version` and `sha256` values and leaves the
verified mise executable on `PATH` for the next step.

Call it in a read-only Ubuntu job after checkout and setup-uv with Python 3.15. The Action installs its YAML parser from
the shared hash-checked lock. `workflow` is the path under `.github/workflows`; `step-name` is the exact name of the
mise step in that file. `github-token` needs public release read access. `changed` is `true` only when the two pins
change; `version` omits the leading `v`, and `sha256` is the Linux x64 executable digest. The Action does not update
`mise.lock` or open a PR.

```yaml
- uses: tox-dev/github-workflows/refresh-mise-pin@SHA
id: mise
with:
workflow: .github/workflows/release.yaml
step-name: 🔧 Set up mise (JDKs)
github-token: ${{ github.token }}
- name: Refresh locked JDKs
run: mise lock --bump --minimum-release-age 7d
```

Include `.github/workflows/release.yaml` and `mise.lock` in the updater's artifact and App writer path allowlists. The
writer should run in a separate job; this Action does not request its token. The seven-day cutoff is fixed and cannot be
lowered by an input.

The weekly updater freezes eligible hook revisions with `prek update --freeze --cooldown-days 7`. It then uses
`release-creator hooks` to pin Python hook dependencies under the same cutoff and writes a patch when
`.pre-commit-config.yaml` changes. The generation job has read-only repository permissions; the separate publish job
Expand Down
1 change: 1 addition & 0 deletions changelog.d/+mise-pin.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a keyless Action to refresh the signed mise binary pin after its GitHub Release has aged seven days.
7 changes: 4 additions & 3 deletions pylock.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependency-groups = [
"lock-reader",
"release-notes",
"release-resolver",
"release-mise-editor",
"release-news",
"release-prepare",
"release-validate",
Expand Down Expand Up @@ -3380,7 +3381,7 @@ sha256 = "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"
[[packages]]
name = "pyyaml"
version = "6.0.3"
marker = "\"release-hook-check\" in dependency_groups or \"release-hooks\" in dependency_groups or \"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-shell\" in dependency_groups or \"release-validate\" in dependency_groups or \"test\" in dependency_groups"
marker = "\"release-hook-check\" in dependency_groups or \"release-hooks\" in dependency_groups or \"release-mise-editor\" in dependency_groups or \"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-shell\" in dependency_groups or \"release-validate\" in dependency_groups or \"test\" in dependency_groups"
index = "https://pypi.org/simple/"

[packages.sdist]
Expand Down Expand Up @@ -4846,7 +4847,7 @@ size = 30255
sha256 = "4e8b4e54979b26554c72a7e669009017a7fdd3fb00bbae0b26f82a86636c289f"

[tool.release-creator]
created-at = 2026-10-24 09:55:17.406208+00:00
created-at = 2026-10-24 11:11:49.304279+00:00

[tool.nab]
created-at = 2026-10-24 09:55:17.406208+00:00
created-at = 2026-10-24 11:11:49.304279+00:00
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ lock-tools = [ "nab==0.0.22", "tomlkit>=0.13" ]
lock-reader = [ "certifi>=2026.7.22", "packaging>=26.3" ]
release-notes = [ "release-creator>=1.1.0" ]
release-resolver = [ "uv==0.13.5" ]
release-mise-editor = [ "pyyaml>=6" ]
release-news = [ "release-creator>=1.1.0", "towncrier>=26.9" ]
release-prepare = [ "release-creator>=1.1.0", "towncrier>=26.9", "prek>=0.2" ]
release-validate = [ "release-creator>=1.1.0", "prek>=0.2" ]
Expand Down
70 changes: 70 additions & 0 deletions refresh-mise-pin/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Refresh mise release pin
description: Update a release workflow to a seven-day-old, signature-verified mise binary
inputs:
workflow:
description: Repository-relative workflow containing the pinned mise step
required: true
step-name:
description: Exact name of the mise setup step in that workflow
required: true
github-token:
description: Token with read access to public GitHub releases
required: true
outputs:
changed:
description: Whether the workflow's mise version or digest changed
value: ${{ steps.update.outputs.changed }}
version:
description: Selected mise version without the v prefix
value: ${{ steps.update.outputs.version }}
sha256:
description: SHA256 of the verified Linux x64 mise executable
value: ${{ steps.update.outputs.sha256 }}
runs:
using: composite
steps:
- name: List upstream releases
shell: bash
env:
GH_TOKEN: ${{ inputs.github-token }}
run: |
gh api --paginate \
--jq '.[] | {tag_name,published_at,prerelease,draft,assets:[.assets[] |
select(.name | endswith("-linux-x64")) | {name,digest,created_at,updated_at}]} | @json' \
'repos/jdx/mise/releases?per_page=100' >"$RUNNER_TEMP/mise-releases.jsonl"
- name: Install locked YAML editor
uses: $/install-locked-tools
with:
groups: release-mise-editor
venv: ${{ runner.temp }}/mise-editor
lock-source: shared
- name: Select seven-day-old release
id: select
shell: bash
run: |
uv run --no-project --python "$RUNNER_TEMP/mise-editor" python \
"$GITHUB_ACTION_PATH/../tools/refresh_mise_pin.py" select \
"$RUNNER_TEMP/mise-releases.jsonl" "$GITHUB_OUTPUT"
- name: Install signature-verified mise
uses: jdx/mise-action@08ae2a091c038e1e05ec6f5115dc5c69d5a2a6b8 # v5.1.2
with:
version: ${{ steps.select.outputs.version }}
mise_dir: ${{ runner.temp }}/refresh-mise-pin
cache: "false"
install: "false"
env: "false"
export_path: "false"
add_shims_to_path: "false"
- name: Update the workflow pin
id: update
shell: bash
env:
WORKFLOW: ${{ inputs.workflow }}
STEP_NAME: ${{ inputs.step-name }}
VERSION: ${{ steps.select.outputs.version }}
EXPECTED_SHA256: ${{ steps.select.outputs.sha256 }}
run: |
uv run --no-project --python "$RUNNER_TEMP/mise-editor" python \
"$GITHUB_ACTION_PATH/../tools/refresh_mise_pin.py" update \
"$WORKFLOW" "$STEP_NAME" "$VERSION" "$EXPECTED_SHA256" \
"$RUNNER_TEMP/refresh-mise-pin/bin/mise" "$GITHUB_OUTPUT"
Loading
Loading