Skip to content

Commit 2afd16d

Browse files
committed
ci: Add GitHub CI workflows for lint, test, build, and release
- Add Go workflow with lint, test, coverage, and multi-platform build jobs - Add release workflow for automated binary releases on tags - Add golangci-lint v2 configuration - Update dependabot to include GitHub Actions ecosystem
1 parent bb78977 commit 2afd16d

File tree

4 files changed

+346
-0
lines changed

4 files changed

+346
-0
lines changed

.github/dependabot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,14 @@ updates:
1111
commit-message:
1212
prefix: chore
1313
include: scope
14+
15+
- package-ecosystem: github-actions
16+
directory: /
17+
schedule:
18+
interval: weekly
19+
labels:
20+
- dependencies
21+
- github-actions
22+
commit-message:
23+
prefix: chore
24+
include: scope

.github/workflows/go.yml

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
types: [opened, synchronize, reopened, ready_for_review]
9+
10+
permissions:
11+
contents: read
12+
pull-requests: write
13+
14+
# Cancel old runs when new commit pushed to PR
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
18+
19+
jobs:
20+
lint:
21+
name: Lint
22+
runs-on: ubuntu-latest
23+
# Skip job if PR is draft or has WIP in title
24+
if: github.event_name != 'pull_request' || (!github.event.pull_request.draft && !contains(github.event.pull_request.title, 'WIP'))
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Go
30+
uses: actions/setup-go@v5
31+
with:
32+
go-version-file: ./go.mod
33+
cache: true
34+
35+
- name: Set up golangci-lint cache
36+
uses: actions/cache@v4
37+
with:
38+
path: ~/.cache/golangci-lint
39+
key: golangci-${{ hashFiles('.golangci.yml') }}-${{ hashFiles('go.sum') }}
40+
restore-keys: |
41+
golangci-${{ hashFiles('.golangci.yml') }}-
42+
golangci-
43+
44+
- name: golangci-lint
45+
uses: golangci/golangci-lint-action@v6
46+
with:
47+
version: latest
48+
only-new-issues: ${{ github.event_name == 'pull_request' }}
49+
skip-cache: true # Use our custom cache
50+
problem-matchers: true
51+
52+
test:
53+
name: Test
54+
runs-on: ubuntu-latest
55+
# Skip job if PR is draft or has WIP in title
56+
if: github.event_name != 'pull_request' || (!github.event.pull_request.draft && !contains(github.event.pull_request.title, 'WIP'))
57+
steps:
58+
- name: Checkout repository
59+
uses: actions/checkout@v4
60+
61+
- name: Set up Go
62+
uses: actions/setup-go@v5
63+
with:
64+
go-version-file: ./go.mod
65+
cache: true
66+
67+
- name: Download dependencies
68+
run: go mod download
69+
70+
- name: Run tests
71+
run: go test -v -race -coverprofile=coverage.out ./...
72+
73+
- name: Upload coverage artifact
74+
uses: actions/upload-artifact@v4
75+
with:
76+
name: coverage
77+
path: coverage.out
78+
79+
coverage:
80+
name: Coverage Report
81+
runs-on: ubuntu-latest
82+
needs: test
83+
if: github.event_name == 'pull_request' && !github.event.pull_request.draft
84+
permissions:
85+
contents: read
86+
actions: read
87+
pull-requests: write
88+
steps:
89+
- name: Checkout repository
90+
uses: actions/checkout@v4
91+
92+
- name: Download coverage artifact
93+
uses: actions/download-artifact@v4
94+
with:
95+
name: coverage
96+
97+
- name: Post coverage report
98+
uses: fgrosse/[email protected]
99+
with:
100+
coverage-artifact-name: "coverage"
101+
coverage-file-name: "coverage.out"
102+
103+
build:
104+
name: Build
105+
runs-on: ubuntu-latest
106+
needs: [lint, test]
107+
strategy:
108+
matrix:
109+
include:
110+
- goos: linux
111+
goarch: amd64
112+
- goos: linux
113+
goarch: arm64
114+
- goos: darwin
115+
goarch: amd64
116+
- goos: darwin
117+
goarch: arm64
118+
- goos: windows
119+
goarch: amd64
120+
steps:
121+
- name: Checkout repository
122+
uses: actions/checkout@v4
123+
124+
- name: Set up Go
125+
uses: actions/setup-go@v5
126+
with:
127+
go-version-file: ./go.mod
128+
cache: true
129+
130+
- name: Build
131+
env:
132+
GOOS: ${{ matrix.goos }}
133+
GOARCH: ${{ matrix.goarch }}
134+
run: |
135+
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
136+
COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "none")
137+
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
138+
LDFLAGS="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}"
139+
140+
BINARY_NAME="atl"
141+
if [ "${{ matrix.goos }}" = "windows" ]; then
142+
BINARY_NAME="atl.exe"
143+
fi
144+
145+
go build -ldflags "${LDFLAGS}" -o "build/${BINARY_NAME}" ./cmd/atl
146+
147+
- name: Upload build artifact
148+
uses: actions/upload-artifact@v4
149+
with:
150+
name: atl-${{ matrix.goos }}-${{ matrix.goarch }}
151+
path: build/

.github/workflows/release.yml

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
name: Release
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
21+
- name: Set up Go
22+
uses: actions/setup-go@v5
23+
with:
24+
go-version-file: ./go.mod
25+
cache: true
26+
27+
- name: Run tests
28+
run: go test -v -race ./...
29+
30+
- name: Build binaries
31+
run: |
32+
VERSION=${GITHUB_REF_NAME}
33+
COMMIT=$(git rev-parse --short HEAD)
34+
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
35+
LDFLAGS="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}"
36+
37+
mkdir -p dist
38+
39+
# Build for each platform
40+
platforms=(
41+
"linux/amd64"
42+
"linux/arm64"
43+
"darwin/amd64"
44+
"darwin/arm64"
45+
"windows/amd64"
46+
)
47+
48+
for platform in "${platforms[@]}"; do
49+
GOOS=${platform%/*}
50+
GOARCH=${platform#*/}
51+
52+
output_name="atl-${GOOS}-${GOARCH}"
53+
if [ "$GOOS" = "windows" ]; then
54+
output_name+=".exe"
55+
fi
56+
57+
echo "Building $output_name..."
58+
GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "${LDFLAGS}" -o "dist/${output_name}" ./cmd/atl
59+
done
60+
61+
# Create archives
62+
cd dist
63+
for file in atl-*; do
64+
if [[ "$file" == *.exe ]]; then
65+
zip "${file%.exe}.zip" "$file"
66+
rm "$file"
67+
else
68+
tar czf "${file}.tar.gz" "$file"
69+
rm "$file"
70+
fi
71+
done
72+
73+
# Generate checksums
74+
sha256sum * > checksums.txt
75+
76+
- name: Generate changelog
77+
id: changelog
78+
run: |
79+
# Get previous tag
80+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
81+
82+
if [ -n "$PREV_TAG" ]; then
83+
echo "Generating changelog from $PREV_TAG to $GITHUB_REF_NAME"
84+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" "$PREV_TAG".."$GITHUB_REF_NAME" --no-merges)
85+
else
86+
echo "No previous tag found, including all commits"
87+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
88+
fi
89+
90+
# Escape for GitHub Actions
91+
echo "changelog<<EOF" >> $GITHUB_OUTPUT
92+
echo "$CHANGELOG" >> $GITHUB_OUTPUT
93+
echo "EOF" >> $GITHUB_OUTPUT
94+
95+
- name: Create Release
96+
uses: softprops/action-gh-release@v2
97+
with:
98+
name: ${{ github.ref_name }}
99+
body: |
100+
## What's Changed
101+
102+
${{ steps.changelog.outputs.changelog }}
103+
104+
## Installation
105+
106+
### macOS (Apple Silicon)
107+
```bash
108+
curl -L https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/atl-darwin-arm64.tar.gz | tar xz
109+
chmod +x atl-darwin-arm64
110+
sudo mv atl-darwin-arm64 /usr/local/bin/atl
111+
```
112+
113+
### macOS (Intel)
114+
```bash
115+
curl -L https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/atl-darwin-amd64.tar.gz | tar xz
116+
chmod +x atl-darwin-amd64
117+
sudo mv atl-darwin-amd64 /usr/local/bin/atl
118+
```
119+
120+
### Linux (x64)
121+
```bash
122+
curl -L https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/atl-linux-amd64.tar.gz | tar xz
123+
chmod +x atl-linux-amd64
124+
sudo mv atl-linux-amd64 /usr/local/bin/atl
125+
```
126+
127+
### Windows
128+
Download `atl-windows-amd64.zip` and add to your PATH.
129+
130+
## Checksums
131+
132+
See `checksums.txt` for SHA256 checksums of all binaries.
133+
files: |
134+
dist/*
135+
draft: false
136+
prerelease: ${{ contains(github.ref_name, '-') }}

.golangci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# golangci-lint v2 configuration
2+
# https://golangci-lint.run/usage/configuration/
3+
version: "2"
4+
5+
run:
6+
timeout: 5m
7+
modules-download-mode: readonly
8+
9+
formatters:
10+
enable:
11+
- gofmt
12+
- goimports
13+
14+
settings:
15+
goimports:
16+
local-prefixes:
17+
- github.com/enthus-appdev/atl-cli
18+
19+
linters:
20+
# Use standard defaults with minimal additions
21+
default: standard
22+
enable:
23+
- bodyclose
24+
- copyloopvar
25+
- misspell
26+
27+
# Disable noisy linters for CLI project
28+
disable:
29+
- errcheck # Too noisy for CLI - lots of intentional ignores
30+
31+
settings:
32+
misspell:
33+
locale: US
34+
35+
staticcheck:
36+
checks:
37+
- all
38+
- -ST1000 # Package comments not required
39+
40+
issues:
41+
exclude-rules:
42+
# Test files have relaxed rules
43+
- path: _test\.go
44+
linters:
45+
- gosec
46+
47+
max-issues-per-linter: 0
48+
max-same-issues: 0

0 commit comments

Comments
 (0)