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
66 changes: 66 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: ci

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod

# gofmt exits 0 even when it reformats, so check for named files instead.
- name: gofmt
run: |
unformatted="$(gofmt -l .)"
if [ -n "$unformatted" ]; then
echo "not gofmt'd:"
echo "$unformatted"
exit 1
fi

- name: vet
run: go vet ./...

- name: test
run: go test -race ./...

# This repo's whole pitch is zero third-party dependencies. Fail loudly
# if a require block ever appears rather than letting it in unnoticed.
- name: no third-party dependencies
run: |
if go list -m all | tail -n +2 | grep .; then
echo "third-party dependencies found; this project vendors none"
exit 1
fi

# Dogfood: the linter must accept the commits it is being built from.
#
# Two things make this fiddlier than it looks on pull_request events:
# checkout is shallow, so the base commit must be fetched before a range
# can resolve against it; and HEAD is the synthetic "Merge <sha> into
# <sha>" commit GitHub builds for the PR, which is not a conventional
# subject. Range endpoints are always included, so --no-merges does not
# drop it — lint up to the branch's real tip instead.
- name: lint own commits
env:
EVENT: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
go build -o /tmp/commitlint .
if [ "$EVENT" = "pull_request" ]; then
git fetch --no-tags --depth=50 origin "$BASE_SHA" "$HEAD_SHA"
/tmp/commitlint lint --range "$BASE_SHA..$HEAD_SHA"
else
git log -1 --format=%B | /tmp/commitlint lint
fi
74 changes: 74 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: release

# Cutting a release is: git tag vX.Y.Z && git push origin vX.Y.Z
on:
push:
tags: ["v*"]

permissions:
contents: write # required to create the release and upload assets

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so release notes can diff against the previous tag

- uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: test
run: go test -race ./...

# A tag that ships a binary claiming a different version is worse than no
# release, so refuse to build one that disagrees with the tag.
- name: build release binaries
env:
VERSION: ${{ github.ref_name }}
run: |
mkdir -p dist
for target in \
linux/amd64 linux/arm64 \
darwin/amd64 darwin/arm64 \
windows/amd64; do
os="${target%/*}"; arch="${target#*/}"
name="commitlint_${VERSION}_${os}_${arch}"
out="dist/${name}/commitlint"
[ "$os" = "windows" ] && out="${out}.exe"
mkdir -p "dist/${name}"
CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" \
go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" -o "$out" .
cp LICENSE README.md "dist/${name}/"
if [ "$os" = "windows" ]; then
(cd dist && zip -qr "${name}.zip" "${name}")
else
(cd dist && tar -czf "${name}.tar.gz" "${name}")
fi
rm -rf "dist/${name}"
done
(cd dist && sha256sum ./*.tar.gz ./*.zip > checksums.txt)
ls -la dist

- name: verify version stamp matches tag
env:
VERSION: ${{ github.ref_name }}
run: |
go build -ldflags "-X main.version=${VERSION}" -o /tmp/commitlint .
got="$(/tmp/commitlint version)"
if [ "$got" != "$VERSION" ]; then
echo "binary reports '$got' but tag is '$VERSION'"
exit 1
fi

- name: publish release
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ github.ref_name }}
run: |
gh release create "$VERSION" \
--title "$VERSION" \
--generate-notes \
dist/*.tar.gz dist/*.zip dist/checksums.txt
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 DivergentCodes

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,32 @@ exec commitlint lint --file "$1"

## Releases

Versions are published as **GitHub tagged releases** with changelogs in the
release notes (no committed changelog file). Pin a released version in CI:
Versions are published as **GitHub tagged releases** with autogenerated
changelogs in the release notes (no committed changelog file). Pin a released
version in CI:

```sh
go install github.com/DivergentCodes/commitlint@v1.0.0
go install github.com/DivergentCodes/commitlint@v1.0.1
```

Each release also carries prebuilt binaries for linux, darwin, and windows
(amd64 and arm64, except windows) plus a `checksums.txt`, for environments
without a Go toolchain:

```sh
curl -sSfL -O https://github.com/DivergentCodes/commitlint/releases/download/v1.0.1/commitlint_v1.0.1_linux_amd64.tar.gz
tar -xzf commitlint_v1.0.1_linux_amd64.tar.gz
./commitlint_v1.0.1_linux_amd64/commitlint version
```

Cutting a release is pushing a tag — `.github/workflows/release.yml` runs the
tests, cross-compiles, verifies the binary reports the tagged version, and
publishes:

```sh
git tag v1.0.1 && git push origin v1.0.1
```

## License

[MIT](LICENSE)
Loading