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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ name: Release
on:
push:
tags: ["v*"]
permissions:
contents: write
permissions: {}
concurrency:
group: release
cancel-in-progress: false
jobs:
build:
permissions:
contents: read
runs-on: ubuntu-26.04
timeout-minutes: 20
strategy:
Expand All @@ -32,6 +33,8 @@ jobs:
uses: jdx/mise-action@6612f0ef07ed2a736cd1e00a94a065522dd41195 # v5.2.5
with:
version: 2026.10.25
# A cache from a pull request could reach the published artifacts.
cache: false
- name: Build
env:
GOOS: ${{ matrix.platform.os }}
Expand All @@ -48,6 +51,8 @@ jobs:
if-no-files-found: error
publish:
needs: build
permissions:
contents: write
runs-on: ubuntu-26.04
timeout-minutes: 10
env:
Expand Down
69 changes: 13 additions & 56 deletions hk.pkl
Original file line number Diff line number Diff line change
@@ -1,63 +1,20 @@
// The hook templates from nnutter/hk-config, which amend hk's configuration.
// Both package paths name the same hk-config version, and that version must
// target the hk pin in mise.toml. The revision is the newest one released for
// that hk version.
amends
"package://github.com/nnutter/hk-config/releases/download/v2.11.1-0/hk-config@2.11.1-0#/Config.pkl"
"package://github.com/nnutter/hk-config/releases/download/v2.11.1-2/hk-config@2.11.1-2#/Config.pkl"

import "package://github.com/jdx/hk/releases/download/v2.11.1/hk@2.11.1#/Builtins.pkl" as Hk
import
"package://github.com/nnutter/hk-config/releases/download/v2.11.1-0/hk-config@2.11.1-0#/Builtins.pkl"
as Extra
"package://github.com/nnutter/hk-config/releases/download/v2.11.1-2/hk-config@2.11.1-2#/Hooks.pkl"
as Hooks

/// Fixtures hold deliberately broken files, so every step skips them.
exclude = List("**/testdata/**")

/// Shared by the implicit check, fix, and pre-commit hooks.
steps {
["constable"] = Extra.constable
["errcheck"] = Hk.err_check
["gitleaks"] = Hk.gitleaks
["go_check_sumtype"] = Extra.go_check_sumtype
["go_fix"] = Hk.go_fix
["go_fumpt"] = Hk.go_fumpt
["go_imports"] = Extra.go_imports
["go_sec"] = Extra.go_sec
["go_vet"] = Hk.go_vet
["go_vuln_check"] = Hk.go_vuln_check
["gomod_tidy"] = Hk.gomod_tidy
["mdlint"] = Extra.mdlint
["newlines"] = Hk.newlines
["nilaway"] = Extra.nilaway
["pkl"] = Hk.pkl
["pkl_format"] = Hk.pkl_format
["skills_ref"] = Extra.skills_ref
["staticcheck"] = Hk.staticcheck
["testifylint"] = Extra.testifylint
["tombi"] = Hk.tombi
["tombi_format"] = Hk.tombi_format
["trailing_whitespace"] = Hk.trailing_whitespace
["yamlfmt"] = Hk.yamlfmt
}

hooks {
// A hook that hk does not create needs an explicit declaration.
["commit-msg"] {
fix = true
steps {
["change-id"] = Extra.timber_commit_msg
}
}
["pre-commit"] {
fix = true
stage = true
stash = "git"
steps {
// No file filter: scan every staged change, including arbitrary types,
// binary files, deletions, and commits without Go or Markdown changes.
// The git-mode scan only sees text diffs, so staged binary bytes are
// checked out to a temporary directory and scanned explicitly.
["gitleaks"] = (Hk.gitleaks) {
scan = "staged"
check =
"gitleaks git --redact --pre-commit --staged --verbose --no-banner && tmp=$(mktemp -d) || exit $?; trap 'rm -rf \"$tmp\"' EXIT INT TERM; git diff --cached --name-only -z --diff-filter=ACMRT > \"$tmp/list\" || exit $?; git checkout-index -z --stdin --prefix=\"$tmp/tree/\" < \"$tmp/list\" || exit $?; mkdir -p \"$tmp/tree\" || exit $?; gitleaks dir --redact --verbose --no-banner \"$tmp/tree\" || exit $?"
}
}
}
}
// The templates build the check, fix, pre-commit, and commit-msg hooks, and
// they order the steps of each hook that fixes: the steps that rewrite files
// run in the order their edits must land, and every step that only reads waits
// for the last fixer, so the readers run together. `check` sets no order.
// `go`, `toml`, `yaml`, and `agentskills` are the groups this repository needs.
hooks = Hooks.all(List("go", "toml", "yaml", "agentskills"))
6 changes: 3 additions & 3 deletions internal/timber/review/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ func prunePatchCache(ctx context.Context, dir string) (err error) {
return err
}
folder, err := os.Open(dir)
if errors.Is(err, os.ErrNotExist) {
return nil
}
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
}
return err
}
defer func() { err = errors.Join(err, folder.Close()) }()
Expand Down
6 changes: 3 additions & 3 deletions internal/timber/review/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,10 @@ func (s Store) Update(action func(*State) error) (err error) {
}
lockPath := s.Path + ".lock"
lock, err := os.OpenFile(lockPath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600)
if errors.Is(err, os.ErrExist) {
return fmt.Errorf("review state is locked: %s; remove the lock only after confirming no writer is running", lockPath)
}
if err != nil {
if errors.Is(err, os.ErrExist) {
return fmt.Errorf("review state is locked: %s; remove the lock only after confirming no writer is running", lockPath)
}
return err
}
defer func() { err = errors.Join(err, lock.Close(), os.Remove(lockPath)) }()
Expand Down
6 changes: 3 additions & 3 deletions internal/timber/review/worktree.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ func WorktreePath(repo string) (string, error) {
// reviewRunning probes an existing lock without creating it.
func reviewRunning(ctx context.Context, path, branch string) (running bool, err error) {
file, err := os.OpenFile(path+".lock", os.O_RDONLY, 0)
if errors.Is(err, os.ErrNotExist) {
return false, nil
}
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return false, nil
}
return false, err
}
defer func() { err = errors.Join(err, file.Close()) }()
Expand Down
43 changes: 43 additions & 0 deletions mise.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
minimum_release_age = "0"

[tools]
jactionlint = "latest"
"github:alecthomas/go-check-sumtype" = "latest"
"github:nnutter/constable" = "latest"
"github:nnutter/mdlint" = "latest"
Expand All @@ -10,6 +11,7 @@ minimum_release_age = "0"
gitleaks = "latest"
go = "latest"
"go:github.com/kisielk/errcheck" = "latest"
"go:github.com/kojah/gohawk" = "latest"
"go:github.com/nnutter/testifylint" = "latest"
"go:go.uber.org/nilaway/cmd/nilaway" = "latest"
"go:golang.org/x/tools/cmd/goimports" = "latest"
Expand Down
Loading