Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pinact for openSUSE:Factory checked in at 2026-05-13 17:22:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pinact (Old) and /work/SRC/openSUSE:Factory/.pinact.new.1966 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pinact" Wed May 13 17:22:39 2026 rev:10 rq:1352980 version:3.10.0 Changes: -------- --- /work/SRC/openSUSE:Factory/pinact/pinact.changes 2026-04-30 20:30:51.615947979 +0200 +++ /work/SRC/openSUSE:Factory/.pinact.new.1966/pinact.changes 2026-05-13 17:25:01.117428789 +0200 @@ -1,0 +2,77 @@ +Wed May 13 11:29:21 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 3.10.0: + * Features + - #1530 Support pinning branches to latest stable tags by the + --branch-to-tag option + The default behabiour isn't changed. + By default, pinact doesn't pin branches such as main or + master. + If you want to pin specific branches, you can use the + --branch-to-tag option. + e.g. + + pinact run --branch-to-tag '^main$' --branch-to-tag '^release/.*$' + + * Dependencies + - fix(deps): update module github.com/urfave/cli/v3 to v3.9.0 + (#1528) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.511.1 (#1527) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.511.0 (#1526) + - chore(deps): update dependency crate-ci/typos to v1.46.1 + (#1525) + - fix(deps): update module github.com/google/go-github/v85 to + v86 (#1524) + - chore(deps): update go module directive to v1.26.3 (#1523) + - chore(deps): update dependency golangci/golangci-lint to + v2.12.2 (#1522) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.510.0 (#1521) + - chore(deps): update dependency aquaproj/aqua to v2.58.1 + (#1520) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.509.0 (#1519) + - chore(deps): update dependency mvdan/gofumpt to v0.10.0 + (#1518) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.508.0 (#1517) + - chore(deps): update dependency goreleaser/goreleaser to + v2.15.4 (#1516) + - chore(deps): update dependency aquaproj/aqua to v2.58.0 + (#1515) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.507.0 (#1514) + - chore(deps): update dependency golangci/golangci-lint to + v2.12.1 (#1513) + - chore(deps): update dependency golangci/golangci-lint to + v2.12.0 (#1510) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.506.0 (#1512) + - chore(deps): update dependency anchore/syft to v1.44.0 + (#1511) + - chore(deps): update dependency crate-ci/typos to v1.46.0 + (#1509) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.505.0 (#1506) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.504.0 (#1505) + - chore(deps): update suzuki-shunsuke/go-release-workflow + action to v8 (#1504) + - chore(deps): update dependency suzuki-shunsuke/ghalint to + v1.5.6 (#1502) + - chore(deps): update suzuki-shunsuke/go-test-full-workflow + action to v5.0.2 (#1503) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.503.0 (#1501) + - chore(deps): update dependency crate-ci/typos to v1.45.2 + (#1500) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.502.0 (#1499) + - chore(deps): update dependency aquaproj/aqua-registry to + v4.501.0 (#1498) + - chore(deps): update dependency suzuki-shunsuke/pinact to + v3.9.2 (#1497) + +------------------------------------------------------------------- Old: ---- pinact-3.9.2.obscpio New: ---- pinact-3.10.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pinact.spec ++++++ --- /var/tmp/diff_new_pack.nryShU/_old 2026-05-13 17:25:02.969505615 +0200 +++ /var/tmp/diff_new_pack.nryShU/_new 2026-05-13 17:25:02.973505781 +0200 @@ -17,7 +17,7 @@ Name: pinact -Version: 3.9.2 +Version: 3.10.0 Release: 0 Summary: CLI to edit GitHub Workflows and pin versions of Actions and Reusable Workflows License: MIT @@ -26,7 +26,7 @@ Source1: vendor.tar.gz BuildRequires: bash-completion BuildRequires: fish -BuildRequires: go1.26 >= 1.26.2 +BuildRequires: go1.26 >= 1.26.3 BuildRequires: zsh %description ++++++ _service ++++++ --- /var/tmp/diff_new_pack.nryShU/_old 2026-05-13 17:25:03.021507772 +0200 +++ /var/tmp/diff_new_pack.nryShU/_new 2026-05-13 17:25:03.029508104 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/suzuki-shunsuke/pinact.git</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">refs/tags/v3.9.2</param> + <param name="revision">refs/tags/v3.10.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.nryShU/_old 2026-05-13 17:25:03.049508933 +0200 +++ /var/tmp/diff_new_pack.nryShU/_new 2026-05-13 17:25:03.057509265 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/suzuki-shunsuke/pinact.git</param> - <param name="changesrevision">f8a8e5121cd646e0866ff15f15ad927675b33c8d</param></service></servicedata> + <param name="changesrevision">fd95c7317488e35c8e642cb7bf51edbf5dbb5ce4</param></service></servicedata> (No newline at EOF) ++++++ pinact-3.9.2.obscpio -> pinact-3.10.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/.golangci.yml new/pinact-3.10.0/.golangci.yml --- old/pinact-3.9.2/.golangci.yml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/.golangci.yml 2026-05-13 11:30:19.000000000 +0200 @@ -30,6 +30,10 @@ - third_party$ - builtin$ - examples$ + rules: + - path: _test\.go + linters: + - goconst formatters: enable: - gci diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/CONTRIBUTING.md new/pinact-3.10.0/CONTRIBUTING.md --- old/pinact-3.9.2/CONTRIBUTING.md 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/CONTRIBUTING.md 2026-05-13 11:30:19.000000000 +0200 @@ -38,7 +38,7 @@ In addition to Go's unit tests, we run integration tests in CI. - [testdata](testdata) -- [workflow](https://github.com/suzuki-shunsuke/pinact/blob/b60761b24a99aa946c45623c2ef2e1e673c257cf/.github/workflows/wc-test.yaml#L34-L67) +- [workflow](.github/workflows/workflow_call_integration_test.yaml) If you change pinact's behaviour, please add tests. Tests also make how the behaviour is changed clear. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/README.md new/pinact-3.10.0/README.md --- old/pinact-3.9.2/README.md 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/README.md 2026-05-13 11:30:19.000000000 +0200 @@ -308,6 +308,33 @@ pinact_version=v3.0.0-local program=pinact ``` +### Pin branches + +pinact >= v3.10.0, [#1529](https://github.com/suzuki-shunsuke/pinact/issues/1529) + +By default, pinact doesn't pin branches such as `main` or `master`. +If you want to pin specific branches, you can use the `--branch-to-tag` option. + +```sh +pinact run --branch-to-tag '<regular expression matching branch name>' +``` + +The value is evaluated as a regular expression with partial match, just like `--include` / `--exclude`. +Anchor with `^...$` for an exact match — for short branch names like `main` this is recommended to avoid matching `mainline` etc. +Versions that don't match any of the supplied regexps continue to error out as before. + +The branch is converted to the **latest stable tag** of the action. Pre-releases are used only when no stable tag exists. + +[`--min-age`](#skip-recently-released-versions) is honored: when set, tags released within the cooldown window are skipped. + +`--branch-to-tag` can be specified multiple times. + +e.g. + +```sh +pinact run --branch-to-tag '^main$' --branch-to-tag '^release/.*$' +``` + ### -diff, -check, -fix options The behaviour of `pinact run` command is changed by command line options `-diff`, `-check`, and `-fix`. @@ -541,10 +568,13 @@ ## Q. Why doesn't pinact pin some actions? +> [!TIP] +> Since v3.10.0, the [`--branch-to-tag`](#pin-branches) option lets you opt-in to pinning specific branches to the latest stable tag of an action. + In some cases pinact doesn't pin versions intentionally, which may confuse you. So we describe the reason here. -pinact doesn't pin actions whose versions aren't semver (e.g. `main`, `master`, `release/v1`). +By default, pinact doesn't pin actions whose versions aren't semver (e.g. `main`, `master`, `release/v1`). This is because pinact is designed as a safe tool so that it doesn't change workflows behaviour. pinact pins actions but doesn't change SHA of actions at the moment when pinact pins versions. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/USAGE.md new/pinact-3.10.0/USAGE.md --- old/pinact-3.9.2/USAGE.md 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/USAGE.md 2026-05-13 11:30:19.000000000 +0200 @@ -11,7 +11,7 @@ pinact [global options] [command [command options]] VERSION: - 3.9.0 + 3.9.2 COMMANDS: init Create .pinact.yaml if it doesn't exist diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/aqua-checksums.json new/pinact-3.10.0/aqua/aqua-checksums.json --- old/pinact-3.9.2/aqua/aqua-checksums.json 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/aqua-checksums.json 2026-05-13 11:30:19.000000000 +0200 @@ -1,133 +1,133 @@ { "checksums": [ { - "id": "github_release/github.com/anchore/syft/v1.43.0/syft_1.43.0_darwin_amd64.tar.gz", - "checksum": "08FD18F55037F999F50B2C2256A9285F0146978A0B16CDC58662ECDC85D0E3C0", + "id": "github_release/github.com/anchore/syft/v1.44.0/syft_1.44.0_darwin_amd64.tar.gz", + "checksum": "C40ECE5407927327F94F35901727DBC604B46857E04F04EC94A310845FB71BDE", "algorithm": "sha256" }, { - "id": "github_release/github.com/anchore/syft/v1.43.0/syft_1.43.0_darwin_arm64.tar.gz", - "checksum": "3640E2181C8BE7A56377F3C96E520D5380C924DBAFD115EE3C8D45FCBC89CAC2", + "id": "github_release/github.com/anchore/syft/v1.44.0/syft_1.44.0_darwin_arm64.tar.gz", + "checksum": "24E4D34078AE81DA7C82539616F0CCAC3E226CF4F74A38CE6FB3463619E50A55", "algorithm": "sha256" }, { - "id": "github_release/github.com/anchore/syft/v1.43.0/syft_1.43.0_linux_amd64.tar.gz", - "checksum": "7B98251D2D08926BB5D4639B56B1F0996A58EF6667C5830E3FE3CD3AD5F4214A", + "id": "github_release/github.com/anchore/syft/v1.44.0/syft_1.44.0_linux_amd64.tar.gz", + "checksum": "0E91737AEE2B5BAF1D255B959630194A302335D848FF97BB07921EB6205B5F5A", "algorithm": "sha256" }, { - "id": "github_release/github.com/anchore/syft/v1.43.0/syft_1.43.0_linux_arm64.tar.gz", - "checksum": "AFE92510C467F952A009B994F2D998FF8F9DD266DC26ECA55D14A0DD46FEC7F2", + "id": "github_release/github.com/anchore/syft/v1.44.0/syft_1.44.0_linux_arm64.tar.gz", + "checksum": "6F6CDCDC695721D91CE756E3B5BC3E3416599C464101F5E32E9C3F33054EE6D9", "algorithm": "sha256" }, { - "id": "github_release/github.com/anchore/syft/v1.43.0/syft_1.43.0_windows_amd64.zip", - "checksum": "C51695D171C61460369DABDD5C71B8F350EF8618466818356A30808D7105C710", + "id": "github_release/github.com/anchore/syft/v1.44.0/syft_1.44.0_windows_amd64.zip", + "checksum": "195E786EB84EC145854F20528992E86637C77D1968731DFE6CE850C90E28F47A", "algorithm": "sha256" }, { - "id": "github_release/github.com/crate-ci/typos/v1.45.1/typos-v1.45.1-aarch64-apple-darwin.tar.gz", - "checksum": "2C31ED16286F26C08AE477FAF001AF8542FF23AEB6E7323BE5F620710C192FB5", + "id": "github_release/github.com/crate-ci/typos/v1.46.1/typos-v1.46.1-aarch64-apple-darwin.tar.gz", + "checksum": "BB5E07DF5C938F41B95903CA8943D9230EB5A4CFBC8A2FF1F3A029D5370926A8", "algorithm": "sha256" }, { - "id": "github_release/github.com/crate-ci/typos/v1.45.1/typos-v1.45.1-aarch64-unknown-linux-musl.tar.gz", - "checksum": "0D3688C607A49FFB6DEDACA6DE44E4217ABEAA5B93228D673DC5CAF76F60489F", + "id": "github_release/github.com/crate-ci/typos/v1.46.1/typos-v1.46.1-aarch64-unknown-linux-musl.tar.gz", + "checksum": "70A8E5A2C6272E25438ED8A9F10C40C9BECF79F2800183FD34603A0840162EAC", "algorithm": "sha256" }, { - "id": "github_release/github.com/crate-ci/typos/v1.45.1/typos-v1.45.1-x86_64-apple-darwin.tar.gz", - "checksum": "70767B5D8D920CBB17B452A6B068E36E1B3FD649089BCE883D3512EB85990326", + "id": "github_release/github.com/crate-ci/typos/v1.46.1/typos-v1.46.1-x86_64-apple-darwin.tar.gz", + "checksum": "BC585C22F2C4F5963AD782DF1D4764A91476D3079477A08833FF87DFA416BB72", "algorithm": "sha256" }, { - "id": "github_release/github.com/crate-ci/typos/v1.45.1/typos-v1.45.1-x86_64-pc-windows-msvc.zip", - "checksum": "A4AE081CB7A403F2B75E8C066AA4A4484207547C4E9EB2B4DF3F68ECDBC5DD3E", + "id": "github_release/github.com/crate-ci/typos/v1.46.1/typos-v1.46.1-x86_64-pc-windows-msvc.zip", + "checksum": "A7B042FC79BF7B73B00ECE054EC3109858E001136C2642F28004544B571D37A2", "algorithm": "sha256" }, { - "id": "github_release/github.com/crate-ci/typos/v1.45.1/typos-v1.45.1-x86_64-unknown-linux-musl.tar.gz", - "checksum": "33447531A0EFF29796D6FB9B555B4628723DB72C6BAD129E168D97AC86CEB0F1", + "id": "github_release/github.com/crate-ci/typos/v1.46.1/typos-v1.46.1-x86_64-unknown-linux-musl.tar.gz", + "checksum": "C574FA505596922BA2E7B1027A0A5B2DF528F399B86B6915D85748186A65CA44", "algorithm": "sha256" }, { - "id": "github_release/github.com/golangci/golangci-lint/v2.11.4/golangci-lint-2.11.4-darwin-amd64.tar.gz", - "checksum": "C900D4048DB75D1EDFD550FD11CF6A9B3008E7CAA8E119FCDDBC700412D63E60", + "id": "github_release/github.com/golangci/golangci-lint/v2.12.2/golangci-lint-2.12.2-darwin-amd64.tar.gz", + "checksum": "F6F06D94B6241521C53D15450C5209B028270BF966F842AFB11C030C79F5BC16", "algorithm": "sha256" }, { - "id": "github_release/github.com/golangci/golangci-lint/v2.11.4/golangci-lint-2.11.4-darwin-arm64.tar.gz", - "checksum": "02DB2A2DAE8B26812E53B0688A6F617E3EF1F489790E829EA22862CF76945675", + "id": "github_release/github.com/golangci/golangci-lint/v2.12.2/golangci-lint-2.12.2-darwin-arm64.tar.gz", + "checksum": "A9C54498731B3128F79E090BE6110F3E5FFFCCC617B08142ED244D4126C73F29", "algorithm": "sha256" }, { - "id": "github_release/github.com/golangci/golangci-lint/v2.11.4/golangci-lint-2.11.4-linux-amd64.tar.gz", - "checksum": "200C5B7503F67B59A6743CCF32133026C174E272B930EE79AA2AA6F37ACA7EF1", + "id": "github_release/github.com/golangci/golangci-lint/v2.12.2/golangci-lint-2.12.2-linux-amd64.tar.gz", + "checksum": "8DF580D2670FED8FA984AAC0507099AF8DF275E665215F5C7A2AE3943893A553", "algorithm": "sha256" }, { - "id": "github_release/github.com/golangci/golangci-lint/v2.11.4/golangci-lint-2.11.4-linux-arm64.tar.gz", - "checksum": "3BCFA2E6F3D32B2BF5CD75EAA876447507025E0303698633F722A05331988DB4", + "id": "github_release/github.com/golangci/golangci-lint/v2.12.2/golangci-lint-2.12.2-linux-arm64.tar.gz", + "checksum": "44CD40A8C76C86755375ADFEEA52CFD3533CB43D7BD647771E0AE065E166DF3A", "algorithm": "sha256" }, { - "id": "github_release/github.com/golangci/golangci-lint/v2.11.4/golangci-lint-2.11.4-windows-amd64.zip", - "checksum": "4932CFCA5E75BF60FE1C576EDF459E5E809E6644664A068185D64B84AF3FAD9E", + "id": "github_release/github.com/golangci/golangci-lint/v2.12.2/golangci-lint-2.12.2-windows-amd64.zip", + "checksum": "BD42E3EBC8CB4ECECB86941983BAAF1DC221BBB04D838E94CE63B49CC91E02BB", "algorithm": "sha256" }, { - "id": "github_release/github.com/golangci/golangci-lint/v2.11.4/golangci-lint-2.11.4-windows-arm64.zip", - "checksum": "FA90179D6377F224798B56BFA308DCD7D62BF28A7AA6889FB180F35B290E3413", + "id": "github_release/github.com/golangci/golangci-lint/v2.12.2/golangci-lint-2.12.2-windows-arm64.zip", + "checksum": "947B9A5BF762D465710B376C156F0184ABB2168378B0826AF1899E0EE7183742", "algorithm": "sha256" }, { - "id": "github_release/github.com/goreleaser/goreleaser/v2.14.1/goreleaser_Darwin_all.tar.gz", - "checksum": "9F2E47F847B4F4177376FC6AA6914FBC7F673F59720076747E738B578C2E896E", + "id": "github_release/github.com/goreleaser/goreleaser/v2.15.4/goreleaser_Darwin_all.tar.gz", + "checksum": "82D730F3366350C90D7E5DF3CF9E8E425FD1C84BF7D7E3E564F92D97C5EA9EA4", "algorithm": "sha256" }, { - "id": "github_release/github.com/goreleaser/goreleaser/v2.14.1/goreleaser_Linux_arm64.tar.gz", - "checksum": "A84D3B27F052C12AD5C8342D7CAF1450A7174A305730AED21D72DB09301E49A5", + "id": "github_release/github.com/goreleaser/goreleaser/v2.15.4/goreleaser_Linux_arm64.tar.gz", + "checksum": "DE01CA1497571E9B348413CD2E7F74BE49B8D57696AE386F7EEDD06176544A88", "algorithm": "sha256" }, { - "id": "github_release/github.com/goreleaser/goreleaser/v2.14.1/goreleaser_Linux_x86_64.tar.gz", - "checksum": "2DF975A7ACBFDEAF888D596CAB0024D48EC7FB7D747E1D08B90948B791F40A5F", + "id": "github_release/github.com/goreleaser/goreleaser/v2.15.4/goreleaser_Linux_x86_64.tar.gz", + "checksum": "AAE00C71A4A6D55E08CCE9273A1516BDCE33C1E07CFFB7E502FA6FEC4377DEDE", "algorithm": "sha256" }, { - "id": "github_release/github.com/goreleaser/goreleaser/v2.14.1/goreleaser_Windows_arm64.zip", - "checksum": "7DFCEF290F25FEC3D09F8A89A8CF4047C0D89889487DAB55C5DDECECE7FFDCB8", + "id": "github_release/github.com/goreleaser/goreleaser/v2.15.4/goreleaser_Windows_arm64.zip", + "checksum": "10227D9DE3EB846F0E58529C22E75DCBD713B67879A7F83912DE7ABE658C5FD7", "algorithm": "sha256" }, { - "id": "github_release/github.com/goreleaser/goreleaser/v2.14.1/goreleaser_Windows_x86_64.zip", - "checksum": "D7A3D8BA795E97AB8C4F8003630D300DA164ADF21FDE5A4049440C20F15C3137", + "id": "github_release/github.com/goreleaser/goreleaser/v2.15.4/goreleaser_Windows_x86_64.zip", + "checksum": "146695F49717DFD79D64D5D6F4B1D25E2B56D73E723BBF68A8DC13CE5CF69693", "algorithm": "sha256" }, { - "id": "github_release/github.com/mvdan/gofumpt/v0.9.2/gofumpt_v0.9.2_darwin_amd64", - "checksum": "4172B912EC514038605F334FEF9ED7B3F12CA3E40024CB0A622EAB3073A55E57", + "id": "github_release/github.com/mvdan/gofumpt/v0.10.0/gofumpt_v0.10.0_darwin_amd64", + "checksum": "30E5B914A824C3B6BD0480E4F493517012167D380DE74643879C50F4AA0C834E", "algorithm": "sha256" }, { - "id": "github_release/github.com/mvdan/gofumpt/v0.9.2/gofumpt_v0.9.2_darwin_arm64", - "checksum": "C241FB742599A6CB0563D7377F59DEF65D451B23DD718DBC6DDF4AB5E695E8F1", + "id": "github_release/github.com/mvdan/gofumpt/v0.10.0/gofumpt_v0.10.0_darwin_arm64", + "checksum": "BA4B348E729CBA915D5C7DC515774E2F2C7CC5C5AD011DE20D34BE10E5A2F906", "algorithm": "sha256" }, { - "id": "github_release/github.com/mvdan/gofumpt/v0.9.2/gofumpt_v0.9.2_linux_amd64", - "checksum": "72CF61B12FEF91EAB6DF6DB4A4284F30616B5EAD330112E28A1FA1CB15E57339", + "id": "github_release/github.com/mvdan/gofumpt/v0.10.0/gofumpt_v0.10.0_linux_amd64", + "checksum": "48EE398EC72AFDACA6ACCB70F5ED741349D5DCCCB52C5BB4C4469D698980B186", "algorithm": "sha256" }, { - "id": "github_release/github.com/mvdan/gofumpt/v0.9.2/gofumpt_v0.9.2_linux_arm64", - "checksum": "5ACAA5A554050F55FC81EF02A8B0D14AB6B3C058A84513885286DC52D3451645", + "id": "github_release/github.com/mvdan/gofumpt/v0.10.0/gofumpt_v0.10.0_linux_arm64", + "checksum": "5D239F93B1ED2DFE74D39B25112BB770A04F6581F986D4B4F5D380521E12CA61", "algorithm": "sha256" }, { - "id": "github_release/github.com/mvdan/gofumpt/v0.9.2/gofumpt_v0.9.2_windows_amd64.exe", - "checksum": "067236B55A8EF4547DDC7D78FBB7A38169DE15BAB02A1763CDE6A132C59DD35C", + "id": "github_release/github.com/mvdan/gofumpt/v0.10.0/gofumpt_v0.10.0_windows_amd64.exe", + "checksum": "20872B464435512B74678B1155B75BD75220DE5737AD8C075B9151C846543697", "algorithm": "sha256" }, { @@ -246,33 +246,33 @@ "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.5/ghalint_1.5.5_darwin_amd64.tar.gz", - "checksum": "CE76AEB46F051D19A618C4E89AE5CA1D37C5A06F1BAC3AFB261FF619FD33045F", + "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.6/ghalint_1.5.6_darwin_amd64.tar.gz", + "checksum": "D2A0E8605333068065DCF4C9B7B7A24891EDA1750AC01FB755DFBA426A390883", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.5/ghalint_1.5.5_darwin_arm64.tar.gz", - "checksum": "DB969E288FC788348AA7C1323096D69DF28B457C70B4194FB76F14AD058C0BE7", + "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.6/ghalint_1.5.6_darwin_arm64.tar.gz", + "checksum": "1262CAC411E27B4653E6B66B7B06580EBCC2026FDD903E12E6CB0E4591639DE6", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.5/ghalint_1.5.5_linux_amd64.tar.gz", - "checksum": "579CBF9024F86A8255CE8ACDD56C7792F0F9A7E76063D64CFB7B66FF65C396E4", + "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.6/ghalint_1.5.6_linux_amd64.tar.gz", + "checksum": "98EE0E3330DE7286F470D1E89C03FF7CE70D7A5998BA0F15969C400447BE579C", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.5/ghalint_1.5.5_linux_arm64.tar.gz", - "checksum": "C3AB464130015D733BFC75A2851F4FC5B3CB966ACA2ED8BC0FA2A029BC0EE6AF", + "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.6/ghalint_1.5.6_linux_arm64.tar.gz", + "checksum": "203A22C70B40BB161626973AD2A8DD06AEB736699FC8E03DD425DEE8FF3406E6", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.5/ghalint_1.5.5_windows_amd64.zip", - "checksum": "58C2589E7455FC05D83A28051F9098984DB3FE6294F0F88AEDC9691AE25EAFF9", + "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.6/ghalint_1.5.6_windows_amd64.zip", + "checksum": "109EA9B39C8E263CEF924BD3B4FE5505964204F934CA60D986F4090D01A99BA5", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.5/ghalint_1.5.5_windows_arm64.zip", - "checksum": "181024767B43BBA5EE15DBEBF8763DA6A1F576AEF5F18D5F44D5572471DA266B", + "id": "github_release/github.com/suzuki-shunsuke/ghalint/v1.5.6/ghalint_1.5.6_windows_arm64.zip", + "checksum": "C1219CAE104EA418A1CB4E7A02526A3FAD384C0788FA3540A86B316BB074D0D8", "algorithm": "sha256" }, { @@ -306,39 +306,39 @@ "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.0/pinact_darwin_amd64.tar.gz", - "checksum": "70F68407A05FA88843FBF9B400D979E6205489EF8AF251DACC21841A07989DF4", + "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.2/pinact_darwin_amd64.tar.gz", + "checksum": "5FACBCD8CD4E20FB88C4EF3ACE9C54B7D295735563634EF4373694CD286BE67A", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.0/pinact_darwin_arm64.tar.gz", - "checksum": "23C8A4EDA8FD7949C8CBB1CFE6F3D01279402FE6201E9CB0A90447A5ECFDEF89", + "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.2/pinact_darwin_arm64.tar.gz", + "checksum": "4A6B481B16B7BB67153F96AAF60CBE61D3A739BDCE35B1CB3FD3DE5372F58C31", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.0/pinact_linux_amd64.tar.gz", - "checksum": "3829DA718DE38B1E914B974C3E77045A256999AF84789437A7305B09130D8A6A", + "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.2/pinact_linux_amd64.tar.gz", + "checksum": "6ADCC8A2217E4114E0841F8BCA0CDDF9958A9C52E3E89760C35B791CDBA1A916", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.0/pinact_linux_arm64.tar.gz", - "checksum": "34A957423002662C6289782B571660BEDA6A37449A76D763C8AD8B1B9A500A54", + "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.2/pinact_linux_arm64.tar.gz", + "checksum": "468BF7AFD0F22B30ECB17FCF02F76D8B5C3BCA59BB85A29017D7DAEBDE96B33F", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.0/pinact_windows_amd64.zip", - "checksum": "B923A567F88417D79CE183E59C2A2372D9CAE9B697A472CE1F95D745932746B1", + "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.2/pinact_windows_amd64.zip", + "checksum": "A7F82E352EB4F706ADDFB864A7C4853F34BDCFC604EBEF8733ADECBBBACAAEEF", "algorithm": "sha256" }, { - "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.0/pinact_windows_arm64.zip", - "checksum": "A2DBFBA73410063EE683636EE61CD57C43F130B7DF90442A40F5D57734C73A5A", + "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.9.2/pinact_windows_arm64.zip", + "checksum": "654FB709F95755202C0C85354217F0A6E56721136B4841B2FCE9B9D568843DE5", "algorithm": "sha256" }, { - "id": "registries/github_content/github.com/aquaproj/aqua-registry/v4.500.0/registry.yaml", - "checksum": "2348CE387546BCD12DFEA1B5316AA42BC3B66C98265A62A6BD39EC6511E009904D92C557897A969D507D49E1914C44D6716EBF2CA8B2C60CA4DD82E8F8436B51", - "algorithm": "sha512" + "id": "registries/github_content/github.com/aquaproj/aqua-registry/v4.511.1/registry.yaml", + "checksum": "33D883B97452563CFD072B26E4ACD0A25A21B7654BC271D110792835F9AA096F", + "algorithm": "sha256" } ] } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/aqua.yaml new/pinact-3.10.0/aqua/aqua.yaml --- old/pinact-3.9.2/aqua/aqua.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/aqua.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,5 +1,5 @@ --- -# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/v2.57.2/json-schema/aqua-yaml.json +# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/v2.58.1/json-schema/aqua-yaml.json # aqua - Declarative CLI Version Manager # https://aquaproj.github.io/ checksum: @@ -7,5 +7,5 @@ require_checksum: true registries: - type: standard - ref: v4.500.0 # renovate: depName=aquaproj/aqua-registry + ref: v4.511.1 # renovate: depName=aquaproj/aqua-registry import_dir: imports diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/ghalint.yaml new/pinact-3.10.0/aqua/imports/ghalint.yaml --- old/pinact-3.9.2/aqua/imports/ghalint.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/ghalint.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: suzuki-shunsuke/[email protected] + - name: suzuki-shunsuke/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/gofumpt.yaml new/pinact-3.10.0/aqua/imports/gofumpt.yaml --- old/pinact-3.9.2/aqua/imports/gofumpt.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/gofumpt.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: mvdan/[email protected] + - name: mvdan/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/golangci-lint.yaml new/pinact-3.10.0/aqua/imports/golangci-lint.yaml --- old/pinact-3.9.2/aqua/imports/golangci-lint.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/golangci-lint.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: golangci/[email protected] + - name: golangci/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/goreleser.yaml new/pinact-3.10.0/aqua/imports/goreleser.yaml --- old/pinact-3.9.2/aqua/imports/goreleser.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/goreleser.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: goreleaser/[email protected] + - name: goreleaser/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/pinact.yaml new/pinact-3.10.0/aqua/imports/pinact.yaml --- old/pinact-3.9.2/aqua/imports/pinact.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/pinact.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: suzuki-shunsuke/[email protected] + - name: suzuki-shunsuke/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/syft.yaml new/pinact-3.10.0/aqua/imports/syft.yaml --- old/pinact-3.9.2/aqua/imports/syft.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/syft.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: anchore/[email protected] + - name: anchore/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/aqua/imports/typos.yaml new/pinact-3.10.0/aqua/imports/typos.yaml --- old/pinact-3.9.2/aqua/imports/typos.yaml 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/aqua/imports/typos.yaml 2026-05-13 11:30:19.000000000 +0200 @@ -1,2 +1,2 @@ packages: - - name: crate-ci/[email protected] + - name: crate-ci/[email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/go.mod new/pinact-3.10.0/go.mod --- old/pinact-3.9.2/go.mod 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/go.mod 2026-05-13 11:30:19.000000000 +0200 @@ -1,12 +1,12 @@ module github.com/suzuki-shunsuke/pinact/v3 -go 1.26.2 +go 1.26.3 require ( github.com/fatih/color v1.19.0 github.com/goccy/go-yaml v1.19.2 github.com/google/go-cmp v0.7.0 - github.com/google/go-github/v85 v85.0.0 + github.com/google/go-github/v86 v86.0.0 github.com/hashicorp/go-version v1.9.0 github.com/lmittmann/tint v1.1.3 github.com/spf13/afero v1.15.0 @@ -15,7 +15,7 @@ github.com/suzuki-shunsuke/slog-error v0.2.2 github.com/suzuki-shunsuke/slog-util v0.3.2 github.com/suzuki-shunsuke/urfave-cli-v3-util v0.2.3 - github.com/urfave/cli/v3 v3.8.0 + github.com/urfave/cli/v3 v3.9.0 golang.org/x/oauth2 v0.36.0 gopkg.in/yaml.v3 v3.0.1 ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/go.sum new/pinact-3.10.0/go.sum --- old/pinact-3.9.2/go.sum 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/go.sum 2026-05-13 11:30:19.000000000 +0200 @@ -22,8 +22,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-github/v80 v80.0.0 h1:BTyk3QOHekrk5VF+jIGz1TNEsmeoQG9K/UWaaP+EWQs= github.com/google/go-github/v80 v80.0.0/go.mod h1:pRo4AIMdHW83HNMGfNysgSAv0vmu+/pkY8nZO9FT9Yo= -github.com/google/go-github/v85 v85.0.0 h1:1+TLFX/akTFXK7o9Z9uAloQGufOn4ySa5DItUM1VWT4= -github.com/google/go-github/v85 v85.0.0/go.mod h1:jYkBnqN+SzR2A2fGKYfbt6DEEQAyxeK0Q2XpPV9ZFsU= +github.com/google/go-github/v86 v86.0.0 h1:S/6aANJhwRm8EQmGKVML3j41yq0h2BsTP8FnDkO7kcA= +github.com/google/go-github/v86 v86.0.0/go.mod h1:zKv1l4SwDXNFMGByi2FWkq71KwSXqj/eQRZuqtmcot8= github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0= github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= @@ -73,8 +73,8 @@ github.com/suzuki-shunsuke/slog-util v0.3.2/go.mod h1:fHyN2kPkinXSgo6GMR0QBj0gd/CpSer0j8bc5C4Pqks= github.com/suzuki-shunsuke/urfave-cli-v3-util v0.2.3 h1:28ZzFUyh118PFMBeHuKYPkIwaxHo+/mJYmljlr9DBRU= github.com/suzuki-shunsuke/urfave-cli-v3-util v0.2.3/go.mod h1:pfMAEENW39YADk1hW/bfHfO4rMu8GKgO4Psh6YY9nyM= -github.com/urfave/cli/v3 v3.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI= -github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= +github.com/urfave/cli/v3 v3.9.0 h1:AV9lIiPv3ukYnxunaCUsHnEozptYmDN2F0+yWqLMn/c= +github.com/urfave/cli/v3 v3.9.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/cli/run/command.go new/pinact-3.10.0/pkg/cli/run/command.go --- old/pinact-3.9.2/pkg/cli/run/command.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/cli/run/command.go 2026-05-13 11:30:19.000000000 +0200 @@ -140,10 +140,15 @@ Usage: "A regular expression to exclude actions", Destination: &flags.Exclude, }, + &cli.StringSliceFlag{ + Name: "branch-to-tag", + Usage: "A regular expression to convert non-semver versions (e.g. branch names) to the latest stable tag. Anchor with ^$ for exact match", + Destination: &flags.BranchToTag, + }, &cli.IntFlag{ Name: "min-age", Aliases: []string{"m"}, - Usage: "Skip versions released within the specified number of days (requires -u)", + Usage: "Skip versions released within the specified number of days (requires -u or --branch-to-tag)", Destination: &flags.MinAge, Sources: cli.EnvVars("PINACT_MIN_AGE"), Validator: func(i int) error { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/config/config.go new/pinact-3.10.0/pkg/config/config.go --- old/pinact-3.9.2/pkg/config/config.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/config/config.go 2026-05-13 11:30:19.000000000 +0200 @@ -18,6 +18,13 @@ "gopkg.in/yaml.v3" ) +const ( + pathPinactYaml = ".pinact.yaml" + pathPinactYml = ".pinact.yml" + pathGitHubPinactYaml = ".github/pinact.yaml" + pathGitHubPinactYml = ".github/pinact.yml" +) + type Config struct { Version int `json:"version,omitempty" jsonschema:"enum=2,enum=3"` Files []*File `json:"files,omitempty" jsonschema:"description=Target files. If files are passed via positional command line arguments, this is ignored"` @@ -52,17 +59,20 @@ func validateSchemaVersion(v int) error { switch v { case 0: - return slogerr.With(errEmptyConfigVersion, //nolint:wrapcheck + return slogerr.With( //nolint:wrapcheck + errEmptyConfigVersion, "docs", "https://github.com/suzuki-shunsuke/pinact/blob/main/docs/codes/002.md", ) case 2: //nolint:mnd - return slogerr.With(errAbandonedConfigVersion, //nolint:wrapcheck + return slogerr.With( //nolint:wrapcheck + errAbandonedConfigVersion, "docs", "https://github.com/suzuki-shunsuke/pinact/blob/main/docs/codes/003.md", ) case 3: //nolint:mnd return nil default: - return slogerr.With(errUnsupportedConfigVersion, //nolint:wrapcheck + return slogerr.With( //nolint:wrapcheck + errUnsupportedConfigVersion, "docs", "https://github.com/suzuki-shunsuke/pinact/blob/main/docs/codes/004.md", ) } @@ -226,7 +236,7 @@ // in order of preference. // Returns the path to the first found configuration file, empty string if none found, or an error. func getConfigPath(fs afero.Fs) (string, error) { - for _, path := range []string{".pinact.yaml", ".github/pinact.yaml", ".pinact.yml", ".github/pinact.yml"} { + for _, path := range []string{pathPinactYaml, pathGitHubPinactYaml, pathPinactYml, pathGitHubPinactYml} { f, err := afero.Exists(fs, path) if err != nil { return "", fmt.Errorf("check if %s exists: %w", path, err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/controller/run/github.go new/pinact-3.10.0/pkg/controller/run/github.go --- old/pinact-3.9.2/pkg/controller/run/github.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/controller/run/github.go 2026-05-13 11:30:19.000000000 +0200 @@ -30,8 +30,13 @@ // It first tries to get the latest version from releases, and if that fails // or returns empty, it falls back to getting the latest version from tags. func (c *Controller) getLatestVersion(ctx context.Context, logger *slog.Logger, owner, repo, currentVersion string) (string, error) { - isStable := isStableVersion(currentVersion) + return c.getLatestVersionWithStable(ctx, logger, owner, repo, isStableVersion(currentVersion)) +} +// getLatestVersionWithStable is the same as getLatestVersion but takes an +// explicit isStable flag instead of inferring it from currentVersion. Used by +// branch-to-tag, which has no semver-shaped currentVersion to infer from. +func (c *Controller) getLatestVersionWithStable(ctx context.Context, logger *slog.Logger, owner, repo string, isStable bool) (string, error) { // Calculate cutoff once for min-age filtering var cutoff time.Time if c.param.MinAge > 0 { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/controller/run/log.go new/pinact-3.10.0/pkg/controller/run/log.go --- old/pinact-3.9.2/pkg/controller/run/log.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/controller/run/log.go 2026-05-13 11:30:19.000000000 +0200 @@ -31,7 +31,14 @@ } } -const levelError = "error" +const ( + levelError = "error" + levelInfo = "info" +) + +const ( + logINFO = "INFO" +) // Output writes formatted log messages with color coding and line information. // It displays the log level, message, file location, and optionally shows @@ -43,7 +50,7 @@ // - line: line information including file path and line number // - newLine: new line content for diff display (empty for no diff) func (l *Logger) Output(level, message string, line *Line, newLine string) { - s := "INFO" + s := logINFO if level == levelError { s = l.red("ERROR") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/controller/run/parse_line.go new/pinact-3.10.0/pkg/controller/run/parse_line.go --- old/pinact-3.9.2/pkg/controller/run/parse_line.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/controller/run/parse_line.go 2026-05-13 11:30:19.000000000 +0200 @@ -204,6 +204,9 @@ case FullCommitSHA: return "", nil default: + if c.matchBranchToTag(action.Version) { + return c.convertBranchToLatestTag(ctx, logger, action) + } return "", ErrCantPinned } // @v1, @v1.0.0 @@ -213,6 +216,41 @@ return c.pinCurrentVersion(ctx, logger, action, typ) } +// matchBranchToTag reports whether v matches any of the --branch-to-tag regexps. +func (c *Controller) matchBranchToTag(v string) bool { + for _, re := range c.param.BranchToTags { + if re.MatchString(v) { + return true + } + } + return false +} + +// convertBranchToLatestTag resolves an action's non-semver version (e.g. a +// branch name) to the latest stable tag of the action's repository and pins +// the line to its commit SHA. Falls back to including pre-releases only when +// no stable tag exists. +func (c *Controller) convertBranchToLatestTag(ctx context.Context, logger *slog.Logger, action *Action) (string, error) { + lv, err := c.getLatestVersionWithStable(ctx, logger, action.RepoOwner, action.RepoName, true) + if err != nil { + return "", fmt.Errorf("get the latest stable version: %w", err) + } + if lv == "" { + lv, err = c.getLatestVersionWithStable(ctx, logger, action.RepoOwner, action.RepoName, false) + if err != nil { + return "", fmt.Errorf("get the latest version: %w", err) + } + if lv == "" { + return "", ErrCantPinned + } + } + sha, _, err := c.repositoriesService.GetCommitSHA1(ctx, logger, action.RepoOwner, action.RepoName, lv, "") + if err != nil { + return "", fmt.Errorf("get a reference: %w", err) + } + return c.patchLine(action, sha, lv), nil +} + // updateToLatestVersion updates an action to its latest version. func (c *Controller) updateToLatestVersion(ctx context.Context, logger *slog.Logger, action *Action) (string, error) { lv, err := c.getLatestVersion(ctx, logger, action.RepoOwner, action.RepoName, action.Version) @@ -303,7 +341,8 @@ // handleUpdateToNewerVersion handles updating to a newer version when available. func (c *Controller) handleUpdateToNewerVersion(ctx context.Context, logger *slog.Logger, action *Action, lv string) (string, error) { if !compareVersion(action.VersionComment, lv) { - logger.Warn("skip updating because the current version is newer than the new version", + logger.Warn( + "skip updating because the current version is newer than the new version", "current_version", action.VersionComment, "new_version", lv, ) @@ -444,7 +483,8 @@ if action.Version == sha { return nil } - return slogerr.With(errors.New("action_version must be equal to commit_hash_of_version_annotation"), //nolint:wrapcheck + return slogerr.With( //nolint:wrapcheck + errors.New("action_version must be equal to commit_hash_of_version_annotation"), "action", action.Name, "action_version", action.Version, "version_annotation", action.VersionComment, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/controller/run/parse_line_internal_test.go new/pinact-3.10.0/pkg/controller/run/parse_line_internal_test.go --- old/pinact-3.9.2/pkg/controller/run/parse_line_internal_test.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/controller/run/parse_line_internal_test.go 2026-05-13 11:30:19.000000000 +0200 @@ -4,6 +4,7 @@ "log/slog" "regexp" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/spf13/afero" @@ -737,4 +738,155 @@ } }) } +} + +func TestController_parseLine_branchToTag(t *testing.T) { //nolint:funlen + t.Parallel() + // Tag/release setup used by all sub-tests: actions/checkout has a stable + // v3.5.2 release plus a v4.0.0-rc.1 pre-release. actions/no-stable has only + // a pre-release. actions/no-tag has neither. + tagsCheckout := &github.ListTagsResult{ + Tags: []*github.RepositoryTag{ + {Name: new("v3.5.2"), Commit: &github.Commit{SHA: new("8e5e7e5ab8b370d6c329ec480221332ada57f0ab")}}, + {Name: new("v4.0.0-rc.1"), Commit: &github.Commit{SHA: new("rcrcrcrcrcrcrcrcrcrcrcrcrcrcrcrcrcrcrcrc")}}, + }, + Response: &github.Response{}, + } + releasesCheckout := &github.ListReleasesResult{ + Releases: []*github.RepositoryRelease{ + {TagName: new("v3.5.2")}, + {TagName: new("v4.0.0-rc.1"), Prerelease: new(true)}, + }, + Response: &github.Response{}, + } + tagsNoStable := &github.ListTagsResult{ + Tags: []*github.RepositoryTag{ + {Name: new("v1.0.0-beta"), Commit: &github.Commit{SHA: new("bebebebebebebebebebebebebebebebebebebebe")}}, + }, + Response: &github.Response{}, + } + releasesNoStable := &github.ListReleasesResult{ + Releases: []*github.RepositoryRelease{ + {TagName: new("v1.0.0-beta"), Prerelease: new(true)}, + }, + Response: &github.Response{}, + } + tagsNoTag := &github.ListTagsResult{Tags: []*github.RepositoryTag{}, Response: &github.Response{}} + releasesNoTag := &github.ListReleasesResult{Releases: []*github.RepositoryRelease{}, Response: &github.Response{}} + + // actions/min-age has v2.0.0 (recent, 1 day ago) and v1.0.0 (older, 30 days ago). + // With --min-age 7, v2.0.0 must be skipped and v1.0.0 chosen. + now := time.Date(2026, 5, 13, 0, 0, 0, 0, time.UTC) + tagsMinAge := &github.ListTagsResult{ + Tags: []*github.RepositoryTag{ + {Name: new("v2.0.0"), Commit: &github.Commit{SHA: new("2222222222222222222222222222222222222222")}}, + {Name: new("v1.0.0"), Commit: &github.Commit{SHA: new("1111111111111111111111111111111111111111")}}, + }, + Response: &github.Response{}, + } + releasesMinAge := &github.ListReleasesResult{ + Releases: []*github.RepositoryRelease{ + {TagName: new("v2.0.0"), PublishedAt: &github.Timestamp{Time: now.AddDate(0, 0, -1)}}, + {TagName: new("v1.0.0"), PublishedAt: &github.Timestamp{Time: now.AddDate(0, 0, -30)}}, + }, + Response: &github.Response{}, + } + + commits := map[string]*github.GetCommitSHA1Result{ + "actions/checkout/v3.5.2": {SHA: "8e5e7e5ab8b370d6c329ec480221332ada57f0ab"}, + "actions/no-stable/v1.0.0-beta": {SHA: "bebebebebebebebebebebebebebebebebebebebe"}, + "actions/min-age/v1.0.0": {SHA: "1111111111111111111111111111111111111111"}, + } + + data := []struct { + name string + line string + branchToTag []*regexp.Regexp + minAge int + exp string + isErr bool + }{ + { + name: "main matches and is converted to latest stable tag", + line: " - uses: actions/checkout@main", + branchToTag: []*regexp.Regexp{regexp.MustCompile(`^main$`)}, + exp: " - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2", + }, + { + name: "regex unmatched still errors", + line: " - uses: actions/checkout@main", + branchToTag: []*regexp.Regexp{regexp.MustCompile(`^master$`)}, + isErr: true, + }, + { + name: "no branch-to-tag configured still errors", + line: " - uses: actions/checkout@main", + branchToTag: nil, + isErr: true, + }, + { + name: "falls back to pre-release when no stable tag exists", + line: " - uses: actions/no-stable@develop", + branchToTag: []*regexp.Regexp{regexp.MustCompile(`^develop$`)}, + exp: " - uses: actions/no-stable@bebebebebebebebebebebebebebebebebebebebe # v1.0.0-beta", + }, + { + name: "errors when action has no tag at all", + line: " - uses: actions/no-tag@main", + branchToTag: []*regexp.Regexp{regexp.MustCompile(`^main$`)}, + isErr: true, + }, + { + name: "semver line is unaffected by branch-to-tag", + line: " - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3", + branchToTag: []*regexp.Regexp{regexp.MustCompile(`.*`)}, + exp: " - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2", + }, + { + name: "min-age skips recent stable tag", + line: " - uses: actions/min-age@main", + branchToTag: []*regexp.Regexp{regexp.MustCompile(`^main$`)}, + minAge: 7, + exp: " - uses: actions/min-age@1111111111111111111111111111111111111111 # v1.0.0", + }, + } + logger := slog.New(slog.DiscardHandler) + for _, d := range data { + t.Run(d.name, func(t *testing.T) { + t.Parallel() + fs := afero.NewMemMapFs() + ctrl := New(&github.RepositoriesServiceImpl{ + Tags: map[string]*github.ListTagsResult{ + "actions/checkout/0": tagsCheckout, + "actions/no-stable/0": tagsNoStable, + "actions/no-tag/0": tagsNoTag, + "actions/min-age/0": tagsMinAge, + }, + Releases: map[string]*github.ListReleasesResult{ + "actions/checkout/0": releasesCheckout, + "actions/no-stable/0": releasesNoStable, + "actions/no-tag/0": releasesNoTag, + "actions/min-age/0": releasesMinAge, + }, + Commits: commits, + }, nil, nil, fs, &config.Config{Separator: " # "}, &ParamRun{ + BranchToTags: d.branchToTag, + MinAge: d.minAge, + Now: now, + }) + line, err := ctrl.parseLine(t.Context(), logger, d.line) + if err != nil { + if d.isErr { + return + } + t.Fatal(err) + } + if d.isErr { + t.Fatalf("expected error, got line %q", line) + } + if line != d.exp { + t.Fatalf("wanted %s, got %s", d.exp, line) + } + }) + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/controller/run/run.go new/pinact-3.10.0/pkg/controller/run/run.go --- old/pinact-3.9.2/pkg/controller/run/run.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/controller/run/run.go 2026-05-13 11:30:19.000000000 +0200 @@ -32,6 +32,7 @@ Review *Review Includes []*regexp.Regexp Excludes []*regexp.Regexp + BranchToTags []*regexp.Regexp MinAge int Now time.Time Format string @@ -219,7 +220,8 @@ if code == http.StatusUnprocessableEntity { level = slog.LevelWarn } - slogerr.WithError(logger, err).Log(ctx, level, "create a review comment", + slogerr.WithError(logger, err).Log( + ctx, level, "create a review comment", "review_repo_owner", c.param.Review.RepoOwner, "review_repo_name", c.param.Review.RepoName, "review_pr_number", c.param.Review.PullRequest, @@ -260,7 +262,8 @@ if code == http.StatusUnprocessableEntity { level = slog.LevelWarn } - slogerr.WithError(logger, err).Log(ctx, level, "create a review comment", + slogerr.WithError(logger, err).Log( + ctx, level, "create a review comment", "review_repo_owner", c.param.Review.RepoOwner, "review_repo_name", c.param.Review.RepoName, "review_pr_number", c.param.Review.PullRequest, @@ -288,7 +291,7 @@ if !c.param.Check && c.param.Fix && !c.param.Diff { return } - level := "info" + level := levelInfo if c.param.Check { level = levelError } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/controller/run/sarif.go new/pinact-3.10.0/pkg/controller/run/sarif.go --- old/pinact-3.9.2/pkg/controller/run/sarif.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/controller/run/sarif.go 2026-05-13 11:30:19.000000000 +0200 @@ -56,7 +56,7 @@ results := make([]sarif.Result, 0, len(c.param.Findings)) for _, f := range c.param.Findings { ruleID := ruleUnpinnedAction - level := "error" + level := levelError var msg string if f.Message != "" { // Parse error diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/di/flag.go new/pinact-3.10.0/pkg/di/flag.go --- old/pinact-3.9.2/pkg/di/flag.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/di/flag.go 2026-05-13 11:30:19.000000000 +0200 @@ -34,12 +34,13 @@ CWD string - FixCount int - PR int - MinAge int - Include []string - Exclude []string - Args []string + FixCount int + PR int + MinAge int + Include []string + Exclude []string + BranchToTag []string + Args []string } const defaultGitHubAPIURL = "https://api.github.com" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/di/run.go new/pinact-3.10.0/pkg/di/run.go --- old/pinact-3.9.2/pkg/di/run.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/di/run.go 2026-05-13 11:30:19.000000000 +0200 @@ -119,6 +119,10 @@ if err != nil { return nil, fmt.Errorf("parse exclude: %w", err) } + branchToTags, err := compileRegexps(flags.BranchToTag) + if err != nil { + return nil, fmt.Errorf("parse branch-to-tag: %w", err) + } param := &run.ParamRun{ WorkflowFilePaths: flags.Args, ConfigFilePath: flags.Config, @@ -134,6 +138,7 @@ Review: review, Includes: includes, Excludes: excludes, + BranchToTags: branchToTags, MinAge: flags.MinAge, Now: time.Now(), Format: flags.Format, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/github/github.go new/pinact-3.10.0/pkg/github/github.go --- old/pinact-3.9.2/pkg/github/github.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/github/github.go 2026-05-13 11:30:19.000000000 +0200 @@ -12,7 +12,7 @@ "log/slog" "net/http" - "github.com/google/go-github/v85/github" + "github.com/google/go-github/v86/github" "github.com/suzuki-shunsuke/ghtkn-go-sdk/ghtkn" "github.com/suzuki-shunsuke/urfave-cli-v3-util/keyring/ghtoken" "golang.org/x/oauth2" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pinact-3.9.2/pkg/github/service.go new/pinact-3.10.0/pkg/github/service.go --- old/pinact-3.9.2/pkg/github/service.go 2026-04-29 03:51:07.000000000 +0200 +++ new/pinact-3.10.0/pkg/github/service.go 2026-05-13 11:30:19.000000000 +0200 @@ -6,7 +6,7 @@ "log/slog" "net/http" - "github.com/google/go-github/v85/github" + "github.com/google/go-github/v86/github" ) // RepositoriesService defines the interface for GitHub Repositories API operations. ++++++ pinact.obsinfo ++++++ --- /var/tmp/diff_new_pack.nryShU/_old 2026-05-13 17:25:03.421524365 +0200 +++ /var/tmp/diff_new_pack.nryShU/_new 2026-05-13 17:25:03.441525194 +0200 @@ -1,5 +1,5 @@ name: pinact -version: 3.9.2 -mtime: 1777427467 -commit: f8a8e5121cd646e0866ff15f15ad927675b33c8d +version: 3.10.0 +mtime: 1778664619 +commit: fd95c7317488e35c8e642cb7bf51edbf5dbb5ce4 ++++++ vendor.tar.gz ++++++ ++++ 199903 lines of diff (skipped)
