This project uses go-semantic-release to automate version management and package releases.
When commits are pushed to the main branch, the GitHub Actions workflow automatically:
- Analyzes commit messages since the last release
- Determines the next version number based on the changes
- Generates release notes from commit messages
- Creates a new Git tag
- Publishes a GitHub release with generated changelog
Semantic release uses the Conventional Commits specification to determine version bumps:
<type>(<scope>): <subject>
<body>
<footer>
fix:- Patches a bug (PATCH version bump: 1.0.0 → 1.0.1)feat:- Introduces a new feature (MINOR version bump: 1.0.0 → 1.1.0)BREAKING CHANGE:in footer or!after type - Breaking change (MAJOR version bump: 1.0.0 → 2.0.0)docs:- Documentation changes only (no version bump)chore:- Maintenance tasks (no version bump)test:- Adding or updating tests (no version bump)refactor:- Code changes that neither fix bugs nor add features (no version bump)perf:- Performance improvements (no version bump by default — onlyfix:,feat:, and breaking changes trigger releases)ci:- CI/CD changes (no version bump)build:- Build system changes (no version bump)style:- Code style changes (no version bump)
fix: resolve nil pointer in ml_dsa_87 signature verification
The cryptoSignVerify function was not properly handling nil public keys,
causing a panic. This change adds proper validation.
fix(crypto): correct byte order in key serialization
feat: add NewMLDSA87FromSecretKey function
This allows creating an MLDSA87 instance directly from a secret key
without requiring the original seed.
feat(wallet): support for ML-DSA-87 wallet generation
Using BREAKING CHANGE: in the footer:
feat: update to FIPS 204 final standard
BREAKING CHANGE: The ML-DSA-87 algorithm has been updated to comply
with the final FIPS 204 standard. Key formats and signatures from
previous versions are incompatible.
Using ! after the type:
feat!: rename package from qrllib to go-qrllib
The main package has been renamed to align with Go module naming
conventions. All import paths must be updated.
docs: update README with installation instructions
chore: update dependencies
test: add integration tests for sphincsplus
ci: add code coverage reporting
This section logs behavioural changes that callers may notice between
releases, separate from the auto-generated changelog. Each entry should
also be reflected in the commit message that introduces it (with a
BREAKING CHANGE: footer where appropriate so semantic-release picks
it up).
Public ML-DSA-87 signing — MLDSA87.Sign, MLDSA87.SignAttached,
wallet/ml_dsa_87.Wallet.Sign, and crypto.Signer-style
CryptoSigner.Sign — is now always hedged as per FIPS 204 (the
recommended mode). Each call mixes fresh crypto/rand randomness into
the per-signature RND_BYTES value, so two calls with the same
(key, ctx, message) now produce distinct signatures. Both still
verify under the same public key — verification is unchanged and
existing verifiers, on-chain or off, are unaffected.
The previous deterministic-by-default mode is no longer the default,
but FIPS 204 deterministic mode (rnd = 32 zero bytes) remains
explicitly reachable via two equivalent public paths for protocols
that need it (RANDAO-style verifiable beacon contributions,
test-vector reproduction):
MLDSA87.SignDeterministic(ctx, msg)— thin convenience helper that signs withrnd = 0^32. Recommended entry point when the deterministic property is itself a protocol requirement.crypto.Signer.Sign(deterministicReader, …)— useful when integrating with code that drives randomness through Go'scrypto.Signerinterface; pass anio.Readerreturning 32 deterministic bytes (e.g.bytes.NewReader(make([]byte, 32))).
Both paths route into the same internal entry point and produce byte-identical signatures for byte-identical input.
The MLDSA87.randomizedSigning bool field was removed from the struct
(positional struct literals like &MLDSA87{pk, sk, seed, false} will
no longer compile — use the New() / NewMLDSA87FromSeed() /
NewMLDSA87FromHexSeed() constructors).
crypto.Signer.Sign now also honours its rand io.Reader parameter
(previously discarded): if non-nil, RND_BYTES are read from the
caller-supplied source; if nil, crypto/rand is used.
- Develop your changes in a feature branch
- Create commits following the conventional commit format
- Open a pull request to
main - Merge the PR - The release workflow triggers automatically
- New release is published if there are releasable commits
Do not create or push version tags manually. go-semantic-release
derives the next version from existing GitHub releases, not tags, so a
manually pushed tag is silently adopted when the version counter later
reaches it — this is how the v0.2.0 release ended up pointing at code 80
commits older than its release notes describe (and module-proxy caching
makes that permanent). If a release must be forced, land a conventional
fix:/feat: commit and let the workflow cut it.
This project follows Semantic Versioning:
- MAJOR version: Incompatible API changes
- MINOR version: New functionality in a backward compatible manner
- PATCH version: Backward compatible bug fixes
During initial development (0.x.y versions):
- MINOR version: Breaking changes (
feat!:/BREAKING CHANGE:) and new features (feat:) — the two are indistinguishable in the version number below 1.0.0 - PATCH version: Bug fixes (
fix:) only
The workflow is configured with allow-initial-development-versions: true to handle this correctly.
The changelog is automatically generated in the GitHub release notes based on commit messages. To get well-formatted release notes:
- Write clear, descriptive commit messages
- Use the appropriate commit type
- Include relevant details in the commit body
- Reference issues with
#123orfixes #123
.github/workflows/release.yml- GitHub Actions workflow.releaserc.json- Semantic release configuration
To skip the release process for a commit, add [skip ci] or [ci skip] to the commit message:
docs: update contributing guidelines [skip ci]
- Atomic commits: Each commit should represent a single logical change
- Descriptive subjects: Keep under 72 characters, use imperative mood
- Detailed bodies: Explain the what and why, not the how
- Reference issues: Link to relevant GitHub issues
- Breaking changes: Always document in the footer with
BREAKING CHANGE: - Scope usage: Use consistent scopes like
(crypto),(wallet),(xmss)for clarity
- Check that commits follow the conventional format
- Verify that commit types warrant a release (
fix:,feat:, orBREAKING CHANGE:) - Review the GitHub Actions logs for errors
- Review commit messages - ensure types are correct
- For breaking changes, verify
BREAKING CHANGE:is in the footer or!is used - Check that the base branch is correct
- Verify the
GITHUB_TOKENhas sufficient permissions - Check that the workflow has write access to contents
- Review the Actions logs for specific error messages