Skip to content

post_version hook aborts entire 'semver set' run when hook target file is missing #171

Description

@justinmchase

Description

When a post_version hook (replace, patch, or regexp) in .github/version.yml references a file that doesn't exist, the resulting Deno.errors.NotFound propagates uncaught out of postVersionHook (src/hooks/post.ts), through the set command handler, and the semver process exits non-zero.

This aborts the entire version-set operation, even though:

  • The VERSION file write already happened.
  • Any earlier hooks in the same on.post list already ran successfully.

Callers that shell out to semver set (e.g. our internal release-automation webhook) then treat the whole operation as failed and roll it back / never commit, even though the only real problem is one misconfigured hook referencing a file that no longer exists in that particular repo.

Repro

.github/version.yml contains a regexp hook pointing at a file that was since removed:

on:
  post:
    - kind: regexp
      file: .github/README.md
      pattern: '\[\d+\.\d+\.\d+\]'

Running semver set 1.17.0 when .github/README.md doesn't exist produces:

Invoking post_version hook...
replacing [1.16.0] -> 1.17.0 in .github/plugin.json
replacing [1.16.0] -> 1.17.0 in .github/.codex-plugin/plugin.json
replacing [1.16.0] -> 1.17.0 in .github/.claude-plugin/plugin.json
replacing [1.16.0] -> 1.17.0 in .github/plugin/marketplace.json
replacing [1.16.0] -> 1.17.0 in .claude-plugin/marketplace.json

then exits non-zero with:

NotFound: No such file or directory (os error 2): readfile '.github/README.md'
    at async Object.readTextFile (ext:deno_fs/30_fs.js:1:10081)
    at async Object.regexp (file:///.../src/hooks/regexp.ts:13:20)
    at async postVersionHook (file:///.../src/hooks/post.ts:40:11)
    at async Object.handler (file:///.../src/commands/set.ts:29:5) {
  code: "ENOENT"
}

Note that four of the five replace hooks above already succeeded before the failing regexp hook — but because the whole process exits non-zero, a caller has no way to keep any of that work.

Requested behavior

Treat a missing hook target file as a recoverable warning rather than a fatal error:

  • Continue running the remaining configured hooks instead of aborting the whole on.post list.
  • Exit 0 overall (the version was still set correctly).
  • Surface which hook(s) failed and why in a way callers can detect programmatically — e.g. via the existing GITHUB_OUTPUT mechanism already used for version/dotnet/docker outputs (writeGithubOutput in src/util/version.ts), as a new hook_warnings field.

Other hook error types (unknown kind, invalid YAML, etc.) should stay fail-fast as-is — this is specifically about a hook's file not existing.

I'll follow up with a PR implementing this.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions