From 62232d721023f6b594aedf974d43bed3e8a5c884 Mon Sep 17 00:00:00 2001 From: Yazeed Al Oyoun Date: Wed, 11 Nov 2026 12:34:08 -0600 Subject: [PATCH] ci: the release moves winget's first-version pull request to each release until it is merged The release skipped winget until a moderator merged the first version, so microsoft/winget-pkgs#469298 stayed at 2.2.0 through 2.3.0 and 2.4.0. pkg/winget/move-pr.sh moves it: one commit replacing the version folder's manifests (only the version, download, SHA-256, date and release notes link may change), then the title and description. update-winget runs it on a tag, prints the change on a dry run, and commit-package-files keeps the manifests in pkg/winget/. Run from the 2.2.0 commit it writes the 2.4.0 manifests moved by hand on 2026-11-11, byte for byte. RELEASE.md's verification opens every submission still under review. --- .github/workflows/release.yml | 63 ++++++++-- CHANGELOG.md | 2 +- RELEASE.md | 13 +- pkg/winget/move-pr.sh | 124 +++++++++++++++++++ pkg/winget/yazeed.proc-cli.installer.yaml | 8 +- pkg/winget/yazeed.proc-cli.locale.en-US.yaml | 4 +- pkg/winget/yazeed.proc-cli.yaml | 2 +- 7 files changed, 192 insertions(+), 24 deletions(-) create mode 100755 pkg/winget/move-pr.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b3bf0c..d018919 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -815,14 +815,20 @@ jobs: exit 1 done + # winget-releaser builds on the last version in winget-pkgs, so until a + # moderator merges the first one, its open pull request is moved to each + # release instead (move-pr.sh), or it would land at the version it was + # opened with (2.2.0 at the 2.4.0 release). A dry run prints what the move + # would change, for the version in Cargo.toml, and pushes nothing update-winget: name: Update winget needs: create-release - if: github.event_name == 'push' runs-on: ubuntu-latest + outputs: + listed: ${{ steps.listed.outputs.listed }} steps: - # winget-releaser builds on the last version in winget-pkgs, so until - # the first one is merged there is nothing to update yet + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Check that yazeed.proc-cli is in winget-pkgs id: listed env: @@ -831,14 +837,32 @@ jobs: if gh api repos/microsoft/winget-pkgs/contents/manifests/y/yazeed/proc-cli > /dev/null 2>&1; then echo "listed=true" >> "$GITHUB_OUTPUT" else - echo "::notice::yazeed.proc-cli is not in winget-pkgs yet, so winget is not updated for this release" echo "listed=false" >> "$GITHUB_OUTPUT" fi + - name: Move the first version's pull request to the release + if: steps.listed.outputs.listed == 'false' + env: + GH_TOKEN: ${{ github.event_name == 'push' && secrets.WINGET_TOKEN || github.token }} + run: | + if [ "$GITHUB_EVENT_NAME" = push ]; then + sh pkg/winget/move-pr.sh "${GITHUB_REF_NAME#v}" --push + else + sh pkg/winget/move-pr.sh "$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n 1)" + fi + + - name: Upload the manifests (for main) + if: steps.listed.outputs.listed == 'false' + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: winget-manifests + path: pkg/winget/*.yaml + if-no-files-found: error + # Opens the pull request for the new version in microsoft/winget-pkgs, # from the yazeed/winget-pkgs fork (Komac finds it by that name). Only the # zip: the bare .exe would match the action's default pattern too. - - if: steps.listed.outputs.listed == 'true' + - if: steps.listed.outputs.listed == 'true' && github.event_name == 'push' uses: vedantmgoyal9/winget-releaser@b7370d4d152efdce803a26cc6ca9eee58cb2ad54 # main, 2026-10-07 with: identifier: yazeed.proc-cli @@ -1088,15 +1112,16 @@ jobs: if-no-files-found: error # The files the package jobs wrote go to main in one commit, so main holds - # what was submitted for the release: pkg/nixpkgs/package.nix and the FreeBSD - # port's and pkgsrc package's files. A job's files are taken only when that - # job passed. They can't be in the release commit: their checksums are of + # what was submitted for the release: pkg/nixpkgs/package.nix, the FreeBSD + # port's and pkgsrc package's files and, while winget's first version waits + # for a moderator, its manifests (pkg/winget/). A job's files are taken only + # when that job passed. They can't be in the release commit: their checksums are of # the tag's download, which holds that commit's ID. A dry run shows what it # would commit (with checksums of its tarball of the checkout) and commits # nothing commit-package-files: name: Commit the package files - needs: [update-nixpkgs, update-freebsd, update-pkgsrc] + needs: [update-nixpkgs, update-freebsd, update-pkgsrc, update-winget] if: ${{ !cancelled() && contains(needs.*.result, 'success') }} runs-on: ubuntu-latest permissions: @@ -1127,6 +1152,13 @@ jobs: name: pkgsrc-update path: ${{ runner.temp }}/pkgsrc + - name: Download the winget manifests + if: needs.update-winget.result == 'success' && needs.update-winget.outputs.listed == 'false' + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: winget-manifests + path: ${{ runner.temp }}/winget + # Only the files each job writes: the artifacts also hold the scripts, # which main keeps as they are - name: Commit them to main (a dry run shows the change) @@ -1134,6 +1166,8 @@ jobs: NIXPKGS: ${{ needs.update-nixpkgs.result }} FREEBSD: ${{ needs.update-freebsd.result }} PKGSRC: ${{ needs.update-pkgsrc.result }} + WINGET: ${{ needs.update-winget.result }} + WINGET_LISTED: ${{ needs.update-winget.outputs.listed }} run: | if [ "$NIXPKGS" = success ]; then cp "$RUNNER_TEMP/nixpkgs/package.nix" pkg/nixpkgs/ @@ -1154,6 +1188,15 @@ jobs: else echo "::warning::update-pkgsrc ended $PKGSRC: pkg/pkgsrc/ is left as it is" fi + # Once winget-pkgs has the package, winget-releaser writes each + # release's manifests there, and pkg/winget/ keeps the first version + if [ "$WINGET" = success ] && [ "$WINGET_LISTED" = false ]; then + for f in yazeed.proc-cli.yaml yazeed.proc-cli.locale.en-US.yaml yazeed.proc-cli.installer.yaml; do + cp "$RUNNER_TEMP/winget/$f" pkg/winget/ + done + elif [ "$WINGET" != success ]; then + echo "::warning::update-winget ended $WINGET: pkg/winget/ is left as it is" + fi git diff --stat if [ "$GITHUB_EVENT_NAME" != push ]; then git diff @@ -1167,7 +1210,7 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git commit --quiet --all -m "chore: package files for ${GITHUB_REF_NAME}" \ - -m "The nixpkgs, FreeBSD and pkgsrc files the release's jobs wrote for ${GITHUB_REF_NAME} (run ${GITHUB_RUN_ID})." + -m "The nixpkgs, FreeBSD, pkgsrc and winget files the release's jobs wrote for ${GITHUB_REF_NAME} (run ${GITHUB_RUN_ID})." # main can move while the release runs for _ in 1 2 3; do if git push --quiet origin HEAD:main; then diff --git a/CHANGELOG.md b/CHANGELOG.md index eb91d28..efb808b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **The winget submission is 2.4.0.** microsoft/winget-pkgs#469298, the first version of `yazeed.proc-cli`, was opened at 2.2.0 and still waits for a moderator; it now holds 2.4.0's manifests (the Windows zip's SHA-256 checked against the release's `checksums.txt`), so Windows users get the current release when it is merged, `proc ports` naming every holder (2.3.0) included. RELEASE.md says what to do if another release comes out first. Nothing changed in proc +- **The winget submission is 2.4.0, and each release moves it until it is merged.** microsoft/winget-pkgs#469298, the first version of `yazeed.proc-cli`, was opened at 2.2.0 and still waits for a moderator: the release job skipped winget until then, so it stayed at 2.2.0 through 2.3.0 and 2.4.0. It now holds 2.4.0's manifests (the Windows zip's SHA-256 checked against the release's `checksums.txt`), so Windows users get the current release when it is merged, `proc ports` naming every holder (2.3.0) included. From the next release, `update-winget` moves it itself with `pkg/winget/move-pr.sh`: one commit on top of the pull request's branch replacing the three manifests, where only the version, the download, its SHA-256, the release date and the release notes link may change, then the title and description; a dry run prints the change. The manifests go to `pkg/winget/` on `main` with the other package files. Run from the 2.2.0 commit, the script writes the same 2.4.0 manifests that were moved by hand, byte for byte. RELEASE.md's verification now opens every submission still waiting for review (winget, nixpkgs, FreeBSD, pkgsrc) and checks it offers the new version, its description included. Nothing changed in proc - **Every workflow action runs on Node 24.** Six still ran on Node 20, which GitHub is retiring: `actions/download-artifact` 4.3.0 to 8.0.2, `actions/upload-artifact` 4.6.2 to 7.0.2, `actions/setup-node` 4.4.0 to 6.5.0, `docker/build-push-action` 5.4.0 to 7.4.0, `docker/login-action` 3.7.0 to 4.8.0 and `docker/setup-qemu-action` 3.7.0 to 4.4.0. `cachix/install-nix-action` moved to 31.11.4 and `vmactions/freebsd-vm` to 1.6.0 (FreeBSD 15.1's image now has a UFS root, not ZFS). `setup-node` stays on 6.x: 7.0 no longer exports the placeholder `NODE_AUTH_TOKEN` the npm job's trusted publishing was tested with, so Dependabot leaves 7.x alone until a release's dry run passes on it. CI and the release's dry run passed on the branch before it was merged. Nothing changed in proc diff --git a/RELEASE.md b/RELEASE.md index 4c8e2e2..d43b6f8 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -16,7 +16,7 @@ RUSTDOCFLAGS="-D warnings" cargo doc --no-deps # The docs.rs pages build with no ``` - [ ] CI is green on main, including "Coverage gate" (100% lines across Linux, macOS and Windows; see CONTRIBUTING.md "Coverage"), both "Nix" jobs (the flake builds proc and runs its tests in Nix's sandbox, macOS's included, and the nixpkgs package builds), both "Test (freebsd)"/"Test (netbsd)" jobs (the whole suite in a BSD VM, then the release binary built and run there) and the "Package .deb and .rpm" and "Install the packages" jobs (the four packages install, run and remove in Debian, Ubuntu and Fedora). A tag release does not wait for it. Locally: `scripts/coverage-local.sh` -- [ ] The release workflow's dry run is green: `gh workflow run release.yml --ref main`, then `gh run watch`. It runs every build and package job (`build-bsd` and `package-linux` among them, the release's own forms of CI's BSD and `.deb`/`.rpm` jobs) and assembles the release files with `checksums.txt`, and publishes nothing: the GitHub Release step and the crates.io, npm, PyPI, Homebrew, Scoop, apt, winget and COPR jobs run only for a tag, and the nixpkgs, FreeBSD and pkgsrc jobs run for the version in Cargo.toml and push or file nothing (step 5). Those three build that version from a tarball of the checkout (`git archive --prefix=proc-cli-X.Y.Z/`, which holds what GitHub's download of the tag will: its source hash matched GitHub's for 2.3.0), since a version has no download before its tag. Here, before step 3's bump, that is the last release's version with this release's code, so `update-pkgsrc` may stop: its diff from pkgsrc's copy is empty once pkgsrc has that release, or `COMMIT_MSG` already names the next one. The dry run that must be green in every job is the one step 5 runs after the release commit, which builds the new version itself The PyPI wheels are built and installed on every OS in the dry run (`package-pypi`, `test-pypi`); only `publish-pypi` waits for a tag. Its version checks print instead of failing, since a branch build is a `-dev` build; the tag checks them +- [ ] The release workflow's dry run is green: `gh workflow run release.yml --ref main`, then `gh run watch`. It runs every build and package job (`build-bsd` and `package-linux` among them, the release's own forms of CI's BSD and `.deb`/`.rpm` jobs) and assembles the release files with `checksums.txt`, and publishes nothing: the GitHub Release step and the crates.io, npm, PyPI, Homebrew, Scoop, apt and COPR jobs run only for a tag, the winget job prints what it would change in the first version's pull request, and the nixpkgs, FreeBSD and pkgsrc jobs run for the version in Cargo.toml and push or file nothing (step 5). Those three build that version from a tarball of the checkout (`git archive --prefix=proc-cli-X.Y.Z/`, which holds what GitHub's download of the tag will: its source hash matched GitHub's for 2.3.0), since a version has no download before its tag. Here, before step 3's bump, that is the last release's version with this release's code, so `update-pkgsrc` may stop: its diff from pkgsrc's copy is empty once pkgsrc has that release, or `COMMIT_MSG` already names the next one. The dry run that must be green in every job is the one step 5 runs after the release commit, which builds the new version itself The PyPI wheels are built and installed on every OS in the dry run (`package-pypi`, `test-pypi`); only `publish-pypi` waits for a tag. Its version checks print instead of failing, since a branch build is a `-dev` build; the tag checks them - [ ] The dry run's "Check credentials" job passed and printed no warning. It tries every secret under "Required Secrets" and reads when each expires (GitHub reports a token's expiry, so no date is kept anywhere): one that is invalid or expired fails the job, and the tag's release then publishes nothing; one that expires within 30 days is a warning. Renew it now, set it with `gh secret set `, and run the dry run again - [ ] The credentials outside CI still work. `check-credentials` can't test them, since they never leave the maintainer's Mac, so the release session runs this there: @@ -101,7 +101,7 @@ Update version in ALL of these files: - [ ] `docs/_data/release.yml` — `version` field (the website's header, footer, install page and structured data read it) - [ ] `Cargo.lock` — rebuild after the bump so its `proc-cli` entry changes, and commit it (`flake.nix` reads its version from `Cargo.toml` and its dependencies from `Cargo.lock`, so it needs no bump of its own) -`pkg/aur/PKGBUILD` is not bumped. Both AUR packages are community packages, kept by their own maintainer: `proc-cli` (built from source) and `proc-cli-bin` (the release binaries); they moved from `proc` and `proc-bin`, which are orphaned at 2.1.1, with 2.2.0. The project has no AUR account yet, so the README points Arch users to those packages, and the PKGBUILD stays in the repo for the day the project can co-maintain them (see "After the tag: AUR" below). `pkg/copr/proc-cli.spec` and `pkg/winget/*` are not bumped either: COPR's `sources.sh` sets the spec's version at build time, and winget-releaser writes the manifests into the winget-pkgs pull request. +`pkg/aur/PKGBUILD` is not bumped. Both AUR packages are community packages, kept by their own maintainer: `proc-cli` (built from source) and `proc-cli-bin` (the release binaries); they moved from `proc` and `proc-bin`, which are orphaned at 2.1.1, with 2.2.0. The project has no AUR account yet, so the README points Arch users to those packages, and the PKGBUILD stays in the repo for the day the project can co-maintain them (see "After the tag: AUR" below). `pkg/copr/proc-cli.spec` and `pkg/winget/*.yaml` are not bumped either: COPR's `sources.sh` sets the spec's version at build time, and the release's `update-winget` writes the winget manifests (`pkg/winget/move-pr.sh` while the first version waits for a moderator, which `commit-package-files` brings to `main`; winget-releaser in the winget-pkgs pull request after that). ## 4. Documentation @@ -223,7 +223,8 @@ After tag push, monitor GitHub Actions: - [ ] Scoop bucket updated - [ ] Docker image pushed - [ ] "Update the apt repository" passed: https://proc-cli.com/apt/dists/stable/main/binary-amd64/Packages lists the new version; the job checks it itself, for amd64 and arm64, and fails if it doesn't. Pages keeps only the first deploy of a commit, and the tagged commit was deployed by its own push, before the release had its `.deb` files, so the job deploys main's newest commit instead: the one "Commit the package files" pushed. If that job pushed nothing, this one fails and says so: deploy after the next push to main with `gh workflow run pages.yml --ref main` -- [ ] "Update winget" opened the pull request for the new version on microsoft/winget-pkgs (until the first version is merged it skips, with a notice). The first version, microsoft/winget-pkgs#469298, waits for a moderator; it was opened at 2.2.0 and moved to 2.4.0 on 2026-11-11 (a commit replacing the version folder's three manifests, and the title and description), so it lands at the current release. If a release comes out before it is merged, either move it the same way, or, the day it is merged, rerun this job in the latest release's run so winget catches up: `gh run rerun --job ` (the ids are in `gh run view --json jobs`) +- [ ] "Update winget" passed. Until a moderator merges the first version, microsoft/winget-pkgs#469298, it moves that pull request to the new version (`pkg/winget/move-pr.sh`: one commit replacing the version folder's three manifests, then the title and description), so it lands at the current release; it was opened at 2.2.0 and stayed there through 2.3.0 until it was moved to 2.4.0 by hand on 2026-11-11. Once winget-pkgs has the package, the job opens the new version's own pull request (winget-releaser). If the first version is merged between two releases, rerun this job in the latest release's run so winget catches up: `gh run rerun --job ` (the ids are in `gh run view --json jobs`) +- [ ] Every submission still waiting for review offers the new version, in its title, its files and what its description says: the winget pull request (#469298, while unmerged), the nixpkgs pull request (#581248: title, `package.nix`, and each claim in the description, such as which platforms it was built on), FreeBSD bug 300492 (the newest patch is the new version's, the older ones obsolete) and the pkgsrc problem report. A job that skipped with a notice is not a pass: open each one - [ ] The PPA's builds for the new version succeeded on every release and both architectures (https://launchpad.net/~yazeedaloyoun/+archive/ubuntu/proc-cli/+packages) - [ ] "Update COPR" passed: the build for the new version succeeded on every chroot (https://copr.fedorainfracloud.org/coprs/yazeed/proc-cli/builds/) - [ ] The "Install the PyPI wheel" jobs passed (Linux x86_64 and aarch64, Alpine, macOS arm64 and x86_64, Windows) @@ -231,7 +232,7 @@ After tag push, monitor GitHub Actions: - [ ] "Update nixpkgs" passed: https://github.com/NixOS/nixpkgs/pull/581248 is titled `proc-cli: init at X.Y.Z` and its checks pass; the job's `package.nix` is committed to `main` - [ ] "Update the FreeBSD port" passed: the patch for the new version is on https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=300492 (or its own update bug, once the port is committed) with `maintainer-approval+`; the job's `pkg/freebsd/` files are committed to `main` - [ ] "Update pkgsrc" passed, and its `pkgsrc-update` artifact has the diff and `gnats-fields.json` -- [ ] "Commit the package files" passed: `main` has `chore: package files for vX.Y.Z`, with the files of each of the three jobs that passed (a job that failed leaves its folder as it was, with a warning). It pushes with the workflow's own token, so the commit starts no CI run of its own +- [ ] "Commit the package files" passed: `main` has `chore: package files for vX.Y.Z`, with the files of each of the package jobs that passed, winget's manifests among them until its first version is merged (a job that failed leaves its folder as it was, with a warning). It pushes with the workflow's own token, so the commit starts no CI run of its own - [ ] The after-the-tag steps are done: nixpkgs, the Ubuntu PPA, the FreeBSD port, the pkgsrc update sent (step 5) ## 7. Post-Release Verification @@ -348,13 +349,13 @@ On tag push, GitHub Actions handles: 7. **Scoop**: Update yazeed/scoop-bucket-proc bucket 8. **Docker**: Push to yazeed/proc-cli on Docker Hub, and the same build to yazeed/proc (the image's original name). A separate workflow (`docker.yml`) with its own tag check: it stops if the tag isn't `v` + Cargo.toml's version 9. **apt repository**: `update-apt`, after `commit-package-files`, starts `pages.yml` on main's newest commit and checks that `/apt` lists the release; `pages.yml` deploys proc-cli.com with `/apt` rebuilt from the `.deb` files of the last three releases and signed with `APT_SIGNING_KEY` (`pkg/apt/build-repo.sh`) -10. **winget**: `update-winget` opens the pull request for the new version on microsoft/winget-pkgs from the `yazeed/winget-pkgs` fork, with `WINGET_TOKEN` (winget-releaser; the fork must keep that name). It skips, with a notice, until a first version of `yazeed.proc-cli` is in winget-pkgs +10. **winget**: `update-winget` opens the pull request for the new version on microsoft/winget-pkgs from the `yazeed/winget-pkgs` fork, with `WINGET_TOKEN` (winget-releaser; the fork must keep that name), once a first version of `yazeed.proc-cli` is in winget-pkgs. Until then it moves the first version's open pull request to the new version (`pkg/winget/move-pr.sh`), and its manifests go to `pkg/winget/` on `main` 11. **COPR**: `update-copr` sends the version to the project's custom webhook (`COPR_WEBHOOK`). COPR runs the package's build script (`pkg/copr/copr-build.sh`, kept in COPR), which fetches `pkg/copr/sources.sh` and the spec at the tag and makes the source RPM: the spec at that version with a changelog entry, the tag's tarball and every crate `Cargo.lock` names. COPR then builds it for each chroot of `yazeed/proc-cli` (Fedora, EPEL 9 and 10, Amazon Linux 2023); the job follows the build on COPR's API and fails if it fails. Fedora's new releases join the project by themselves ("Follow Fedora branching"). To change the script COPR keeps, edit the file and run `copr-cli edit-package-custom proc-cli --script pkg/copr/copr-build.sh --script-builddeps "curl cargo tar xz"`; `pkg/copr/srpm.sh X.Y.Z` builds the same source RPM locally 12. **PyPI**: `pip install proc-cli` (also `pipx` and `uv tool`). `package-pypi` repacks the five release binaries into five wheels with `pkg/pypi/build-wheels.py` (standard library only; no maturin, no second Rust build): `manylinux_2_17`/`manylinux2014`/`musllinux_1_1` for Linux x86_64 and aarch64 (the static musl binaries), `macosx_10_12_x86_64` and `macosx_11_0_arm64` (each binary's own minimum macOS, read with `vtool -show-build`; check it again when the build target changes) and `win_amd64`, each holding the binary as the `proc` command. It checks the metadata with `twine check` and expects exactly five wheels. `test-pypi` installs the wheel with pip on its own OS (Ubuntu x86_64 and arm64, an Alpine container for musl, macOS arm64 and Intel, Windows) with `pkg/pypi/test-install.sh` and checks `proc --version`. `publish-pypi` runs for a tag, after the GitHub Release and every `test-pypi` job, and uploads the wheels with trusted publishing (environment `pypi`). The wheels are not release files. There is no TestPyPI run: its `proc-cli` belongs to an unrelated project 13. **nixpkgs**: `update-nixpkgs` moves `pkg/nixpkgs/package.nix` to the release with its hashes, builds it with its tests, and brings it to the nixpkgs pull request with `NIXPKGS_FORK_TOKEN` (see "After the tag: nixpkgs"). It does nothing once nixpkgs has the package 14. **FreeBSD port**: `update-freebsd` moves `sysutils/proc-cli` to the release in a FreeBSD VM with a ports tree, builds and checks it, and files the patch with FreeBSD's Bugzilla with `FREEBSD_BUGZILLA_API_KEY` (see "After the tag: FreeBSD port") 15. **pkgsrc**: `update-pkgsrc` moves `sysutils/proc-cli` to the release in a NetBSD VM, builds and checks it, and uploads the diff and the gnats form's fields; the report is filed by hand (see "After the tag: pkgsrc") -16. **Package files on main**: `commit-package-files` commits the files those three jobs wrote to `pkg/nixpkgs/`, `pkg/freebsd/` and `pkg/pkgsrc/` on `main` (`chore: package files for vX.Y.Z`), each only when its job passed; a dry run shows the change and commits nothing +16. **Package files on main**: `commit-package-files` commits the files those three jobs wrote to `pkg/nixpkgs/`, `pkg/freebsd/` and `pkg/pkgsrc/` on `main`, and the winget manifests to `pkg/winget/` while the first version waits (`chore: package files for vX.Y.Z`), each only when its job passed; a dry run shows the change and commits nothing The GitHub Release, and so every job after it, waits on `check-credentials`, which runs on every tag and dry run (step 1). Docker's workflow runs on its own and logs in itself. diff --git a/pkg/winget/move-pr.sh b/pkg/winget/move-pr.sh new file mode 100755 index 0000000..439c121 --- /dev/null +++ b/pkg/winget/move-pr.sh @@ -0,0 +1,124 @@ +#!/bin/sh +# Moves the open microsoft/winget-pkgs pull request for yazeed.proc-cli's +# first version (from yazeed/winget-pkgs) to VERSION, until winget-pkgs has +# the package; from then on winget-releaser opens each release's own pull +# request, and this does nothing. The pull request waits for a volunteer +# moderator, so without this it would land at whatever version it was opened +# with (2.2.0, still there at the 2.4.0 release). One commit on top of the +# branch replaces the version folder's three manifests, then the title and +# description are moved too. Only the version, the download, its SHA-256 (the +# release's checksums.txt), the release date and the release notes link may +# change: anything else stops it. The new manifests are also written to +# pkg/winget/, which main keeps as what was submitted. +# pkg/winget/move-pr.sh VERSION [--push] +# Without --push it prints the change and pushes nothing. Needs gh, jq and +# sha256sum or shasum; GH_TOKEN to read, and with --push WINGET_TOKEN's (a +# classic token with public_repo, which can push to the fork and edit the pull +# request). PR_HEAD names another commit of the branch to start from, to check +# the script against an earlier state without --push. The release's +# update-winget job runs it (RELEASE.md, step 6). +set -eu + +version=${1:?usage: move-pr.sh VERSION [--push]} +push=${2:-} +here=$(cd "$(dirname "$0")" && pwd) +upstream=microsoft/winget-pkgs +fork=yazeed/winget-pkgs +dir=manifests/y/yazeed/proc-cli +zip=proc-windows-x86_64.exe.zip +files="yazeed.proc-cli.yaml yazeed.proc-cli.locale.en-US.yaml yazeed.proc-cli.installer.yaml" + +fail() { echo "move-pr.sh: $*" >&2; exit 1; } +sha256() { if command -v sha256sum > /dev/null; then sha256sum "$1"; else shasum -a 256 "$1"; fi | cut -d' ' -f1; } + +if gh api "repos/$upstream/contents/$dir" > /dev/null 2>&1; then + echo "winget-pkgs has yazeed.proc-cli: winget-releaser opens each release's pull request" + exit 0 +fi + +prs=$(gh pr list -R "$upstream" --state open --author yazeed --limit 100 \ + --json number,title,headRefName,headRepositoryOwner \ + --jq '[.[] | select(.title | startswith("New package: yazeed.proc-cli version "))]') +[ "$(echo "$prs" | jq length)" -eq 1 ] || + fail "expected one open 'New package: yazeed.proc-cli' pull request on $upstream, found $(echo "$prs" | jq length)" +number=$(echo "$prs" | jq -r '.[0].number') +branch=$(echo "$prs" | jq -r '.[0].headRefName') +[ "$(echo "$prs" | jq -r '.[0].headRepositoryOwner.login')" = yazeed ] || fail "#$number is not from $fork" + +head=$(gh api "repos/$fork/branches/$branch" --jq .commit.sha) +from=${PR_HEAD:-$head} +old=$(gh api "repos/$fork/contents/$dir?ref=$from" --jq '[.[] | select(.type == "dir") | .name] | if length == 1 then .[0] else error("not one version folder") end') || + fail "$fork's $branch at $from does not hold one version folder under $dir" +if [ "$old" = "$version" ]; then + echo "$upstream#$number already offers $version" + exit 0 +fi + +work=$(mktemp -d) +trap 'rm -r "$work"' EXIT +if ! gh release view "v$version" -R yazeed/proc-cli > /dev/null 2>&1; then + [ "$push" != --push ] || fail "v$version has no release to point the manifests at" + echo "v$version has no release yet: a tag's run moves $upstream#$number from $old to it" + exit 0 +fi +gh release download "v$version" -R yazeed/proc-cli -D "$work" -p "$zip" -p checksums.txt +sha=$(sha256 "$work/$zip") +grep -qx "$sha $zip" "$work/checksums.txt" || fail "$zip's SHA-256 $sha is not the one in v$version's checksums.txt" +sha=$(echo "$sha" | tr '[:lower:]' '[:upper:]') +date=$(gh release view "v$version" -R yazeed/proc-cli --json publishedAt --jq '.publishedAt[0:10]') + +o=$(echo "$old" | sed 's/\./\\./g') +for f in $files; do + gh api "repos/$fork/contents/$dir/$old/$f?ref=$from" --jq .content | base64 -d > "$work/old-$f" + sed -e "s/^PackageVersion: $o\$/PackageVersion: $version/" \ + -e "s#/releases/tag/v$o\$#/releases/tag/v$version#" \ + -e "s#/releases/download/v$o/$zip\$#/releases/download/v$version/$zip#" \ + -e "s/^ReleaseDate: .*/ReleaseDate: $date/" \ + -e "s/^ InstallerSha256: .*/ InstallerSha256: $sha/" \ + "$work/old-$f" > "$work/$f" + ! grep -qF "$old" "$work/$f" || fail "$f still names $old after the move: $(grep -F "$old" "$work/$f")" + # Every changed line is one of those + other=$(diff "$work/old-$f" "$work/$f" | grep '^[<>]' | + grep -v -e '^[<>] PackageVersion: ' -e '^[<>] ReleaseNotesUrl: ' -e '^[<>] InstallerUrl: ' \ + -e '^[<>] ReleaseDate: ' -e '^[<>] InstallerSha256: ' || true) + [ -z "$other" ] || fail "$f would change more than the version lines: +$other" +done +grep -qx " InstallerUrl: https://github.com/yazeed/proc-cli/releases/download/v$version/$zip" "$work/yazeed.proc-cli.installer.yaml" || + fail "the installer manifest's InstallerUrl is not v$version's $zip" + +title="New package: yazeed.proc-cli version $version" +gh pr view "$number" -R "$upstream" --json body --jq .body > "$work/old-body" +sed "s/$o/$version/g" "$work/old-body" > "$work/body" + +for f in $files; do diff -u "$work/old-$f" "$work/$f" || true; done +diff -u "$work/old-body" "$work/body" || true +for f in $files; do cp "$work/$f" "$here/$f"; done + +if [ "$push" != --push ]; then + echo "not pushed: with --push, $upstream#$number moves from $old to $version, titled '$title'" + exit 0 +fi +[ "$from" = "$head" ] || fail "PR_HEAD is only for checking, without --push" + +# One commit on top of the branch; the ref moves only if the branch is still +# at the commit read above +tree=$(gh api "repos/$fork/commits/$head" --jq .commit.tree.sha) +jq -n --arg base "$tree" --arg dir "$dir" --arg old "$old" --arg new "$version" \ + --rawfile v "$work/yazeed.proc-cli.yaml" \ + --rawfile l "$work/yazeed.proc-cli.locale.en-US.yaml" \ + --rawfile i "$work/yazeed.proc-cli.installer.yaml" ' + {base_tree: $base, tree: ( + [ "yazeed.proc-cli.yaml", "yazeed.proc-cli.locale.en-US.yaml", "yazeed.proc-cli.installer.yaml" ] + | map({path: "\($dir)/\($old)/\(.)", mode: "100644", type: "blob", sha: null}) + + [ {name: "yazeed.proc-cli.yaml", content: $v}, + {name: "yazeed.proc-cli.locale.en-US.yaml", content: $l}, + {name: "yazeed.proc-cli.installer.yaml", content: $i} ] + | map(if .name then {path: "\($dir)/\($new)/\(.name)", mode: "100644", type: "blob", content: .content} else . end))}' \ + > "$work/tree.json" +newtree=$(gh api -X POST "repos/$fork/git/trees" --input "$work/tree.json" --jq .sha) +commit=$(gh api -X POST "repos/$fork/git/commits" -f message="$title" -f tree="$newtree" -f "parents[]=$head" --jq .sha) +gh api -X PATCH "repos/$fork/git/refs/heads/$branch" -f sha="$commit" -F force=false > /dev/null || + fail "$branch moved while this ran: nothing was changed, run it again" +gh pr edit "$number" -R "$upstream" --title "$title" --body-file "$work/body" > /dev/null +echo "$upstream#$number moved from $old to $version ($commit)" diff --git a/pkg/winget/yazeed.proc-cli.installer.yaml b/pkg/winget/yazeed.proc-cli.installer.yaml index 9032784..f2f0f41 100644 --- a/pkg/winget/yazeed.proc-cli.installer.yaml +++ b/pkg/winget/yazeed.proc-cli.installer.yaml @@ -1,14 +1,14 @@ # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.12.0.schema.json PackageIdentifier: yazeed.proc-cli -PackageVersion: 2.2.0 +PackageVersion: 2.4.0 InstallerType: zip NestedInstallerType: portable -ReleaseDate: 2026-11-01 +ReleaseDate: 2026-11-11 Installers: - Architecture: x64 - InstallerUrl: https://github.com/yazeed/proc-cli/releases/download/v2.2.0/proc-windows-x86_64.exe.zip - InstallerSha256: 534C95064FF425335B8D9F52172D97AAA5AA493D061B51F66B7C9A0DA07C1CA7 + InstallerUrl: https://github.com/yazeed/proc-cli/releases/download/v2.4.0/proc-windows-x86_64.exe.zip + InstallerSha256: F7D10C3FED43213C382E65A214EF6B726E717A0AF5B64A8F2392A763E5D2AA47 NestedInstallerFiles: - RelativeFilePath: proc-windows-x86_64.exe PortableCommandAlias: proc diff --git a/pkg/winget/yazeed.proc-cli.locale.en-US.yaml b/pkg/winget/yazeed.proc-cli.locale.en-US.yaml index 1022807..4a923ca 100644 --- a/pkg/winget/yazeed.proc-cli.locale.en-US.yaml +++ b/pkg/winget/yazeed.proc-cli.locale.en-US.yaml @@ -1,7 +1,7 @@ # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.12.0.schema.json PackageIdentifier: yazeed.proc-cli -PackageVersion: 2.2.0 +PackageVersion: 2.4.0 PackageLocale: en-US Publisher: Yazeed Al Oyoun PublisherUrl: https://github.com/yazeed @@ -20,7 +20,7 @@ Tags: - port - process - process-management -ReleaseNotesUrl: https://github.com/yazeed/proc-cli/releases/tag/v2.2.0 +ReleaseNotesUrl: https://github.com/yazeed/proc-cli/releases/tag/v2.4.0 Documentations: - DocumentLabel: Commands DocumentUrl: https://proc-cli.com/commands diff --git a/pkg/winget/yazeed.proc-cli.yaml b/pkg/winget/yazeed.proc-cli.yaml index 4db6822..698ccc6 100644 --- a/pkg/winget/yazeed.proc-cli.yaml +++ b/pkg/winget/yazeed.proc-cli.yaml @@ -1,7 +1,7 @@ # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.12.0.schema.json PackageIdentifier: yazeed.proc-cli -PackageVersion: 2.2.0 +PackageVersion: 2.4.0 DefaultLocale: en-US ManifestType: version ManifestVersion: 1.12.0