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)

Reply via email to