Modernize versioning: derive from build info, add CI + release workflow#4
Merged
Merged
Conversation
Replaces the hardcoded version string in pdfer.Version() with a lookup against runtime/debug.ReadBuildInfo(). The function now returns whatever version Go's module system resolved for this dependency — matching the git tag a consumer pinned — instead of a constant that had drifted several minor versions behind the actual tags (v1.9.0 was latest, constant said "1.3.0"/"1.3.1"). Returns "(devel)" for local builds and "(unknown)" if build info is unavailable. Honest about its source, impossible to drift. No callers in the repo passed the old format-without-v-prefix expectation; consumers comparing to a literal string will need to update, but no internal test or example does. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The repo previously had no CI and no release automation. A local pre-push hook enforced that pdfer.go's version string changed before push to main, but the actual git tags were created manually and drifted from the constant by several minor versions over time. This adds: - .github/workflows/ci.yml — runs go vet + go test on Go 1.21/1.22/1.23 for every push to main and every PR. Includes a version-guard job that rejects reintroduction of a hardcoded version literal in pdfer.go (catches the exact regression pattern that caused the drift). - .github/workflows/release.yml — manual workflow_dispatch with a version input (e.g., v1.10.0). Validates format, refuses to overwrite existing tags, runs the test suite, creates an annotated tag, pushes it, and publishes a GitHub release with auto-generated notes. - pre-push hook — drops the version-bump enforcement (no longer meaningful now that Version() derives at runtime). Keeps the test runner for fast local feedback. - CONTRIBUTING.md — documents the new release process and removes the defunct "version bump requirement" section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Originally omitted from this PR because the repo had pre-existing gofmt drift across 16 files. Rebased onto main (8b00bd1) which includes the fmt cleanup, so the check can now be enabled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b1833ec to
abe8a3f
Compare
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
The library's printable version and its fetchable version had drifted apart by several minor releases.
pdfer.Version()was a hardcoded string inpdfer.go, manually bumped via commit. Git tags were created manually. There was no CI tying them together.Concretely, at the time of this PR:
Version()returnsv1.5.0throughv1.9.0"1.3.0"(never bumped during five minor releases)origin/main(untagged tip)"1.3.1"A user running
go get …@v1.9.0and thenpdfer.Version()would see"1.3.0". Module fetching itself worked correctly (Go uses tags), but the in-code version was misleading anyone who read it.What this PR does
Eliminates the constant.
Version()now reads the resolved module version viaruntime/debug.ReadBuildInfo(). Returns the git tag a consumer pinned (e.g.,"v1.10.0"),"(devel)"for local builds,"(unknown)"if build info is unavailable. Impossible to drift from the tag.Adds CI (
.github/workflows/ci.yml):go vet+go testagainst Go 1.21, 1.22, 1.23 on every push to main and every PRgofmtcheck (enabled now that style: apply gofmt to entire codebase #5 cleaned up pre-existing drift)version-guardjob that greps for the regression pattern (return "v?N.N.N"inpdfer.go) and fails CI if anyone reintroduces a hardcoded literalAdds release workflow (
.github/workflows/release.yml):workflow_dispatchwithversioninput (e.g.,v1.10.0)Slims the pre-push hook. Drops the version-bump enforcement (no longer meaningful). Keeps the local test runner for fast feedback.
Updates
CONTRIBUTING.md. Removes the defunct "version bump requirement" section, documents the new release dispatch flow.Test plan
go test ./...passes locallygo vet ./...passes locallygofmt -l .is clean after rebase onto style: apply gofmt to entire codebase #5replacedirective:Version()returns the expected pseudo-versionVersion()returns"(devel)"pdfer.go, would have rejected the old onev1.10.0to validate the release path end-to-endKnown follow-ups (deliberately out of scope)
examples/kitchen_sink/main.go:628-634has another hand-maintained version table (per-feature versions like "AcroForm v1.9.0"). Belongs in aCHANGELOG.md, not source — but unrelated to the libraryVersion()issue.v1.10.0to stay monotonically ahead ofv1.9.0.🤖 Generated with Claude Code