Skip to content

Commit 1b29ece

Browse files
authored
CI Pipeline (#1)
* Add CI, release, and dependabot workflows CI runs on push and PR: builds, vets, and tests across Linux/macOS/Windows on Go 1.21 (go.mod minimum) and latest stable. golangci-lint runs as a separate job on Linux. Release fires on vX.Y.Z tag pushes. It verifies the tag lives on main, runs the test suite, and drafts a GitHub Release with auto-generated notes. Tags containing "-" are marked as pre-releases. Because this is a library, no binaries are built — proxy.golang.org picks up the tag and consumers pull source via go get. Dependabot keeps gomod and github-actions deps current. README gains a Releasing section describing the tag-driven flow. * Pin actions to full SHAs and fix lint findings Pin every third-party GitHub Action to a full 40-char commit SHA with the semver in a trailing comment. Tags are mutable; SHAs are not. This defends against supply-chain attacks that move tags to malicious refs (see tj-actions/changed-files, March 2025). Dependabot's github-actions ecosystem keeps these pins current. Bump to latest stable versions while pinning: - actions/checkout v6.0.2 - actions/setup-go v6.4.0 - golangci/golangci-lint-action v9.2.0 - softprops/action-gh-release v3.0.0 Also clear the four errcheck findings golangci-lint v2 flagged on fmt.Fprintf writes to stdout, by switching to cobra's cmd.Printf which swallows the error by design. * Bump to Go 1.25 and fix Windows CI Go 1.25 becomes the minimum supported version in go.mod, and every CI and release job pins to the same version so the matrix is OS-only now. Windows jobs were failing under pwsh: `go test -race -coverprofile=coverage.out -covermode=atomic ./...` was being misparsed, with `.out` treated as a package argument. Force `shell: bash` at the job level so all steps run under the same shell on every runner, which also fixes the failure.
1 parent 0650f61 commit 1b29ece

7 files changed

Lines changed: 117 additions & 6 deletions

File tree

.github/dependabot.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: gomod
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
open-pull-requests-limit: 5
8+
- package-ecosystem: github-actions
9+
directory: /
10+
schedule:
11+
interval: weekly
12+
open-pull-requests-limit: 5

.github/workflows/ci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
test:
14+
name: test (${{ matrix.os }})
15+
runs-on: ${{ matrix.os }}
16+
defaults:
17+
run:
18+
shell: bash
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
os: [ubuntu-latest, macos-latest, windows-latest]
23+
steps:
24+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25+
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
26+
with:
27+
go-version: "1.25"
28+
check-latest: true
29+
- name: Verify modules
30+
run: go mod verify
31+
- name: Build
32+
run: go build ./...
33+
- name: Vet
34+
run: go vet ./...
35+
- name: Test
36+
run: go test -race -coverprofile=coverage.out -covermode=atomic ./...
37+
38+
lint:
39+
name: lint
40+
runs-on: ubuntu-latest
41+
steps:
42+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
43+
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
44+
with:
45+
go-version: "1.25"
46+
check-latest: true
47+
- uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
48+
with:
49+
version: latest
50+
args: --timeout=5m

.github/workflows/release.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags: ["v*"]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
release:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
15+
with:
16+
fetch-depth: 0
17+
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
18+
with:
19+
go-version: "1.25"
20+
check-latest: true
21+
- name: Verify tag is on main
22+
run: |
23+
git fetch origin main
24+
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
25+
echo "::error::tag ${GITHUB_REF_NAME} is not on main"
26+
exit 1
27+
fi
28+
- name: Verify modules
29+
run: go mod verify
30+
- name: Test
31+
run: go test -race ./...
32+
- name: Create GitHub release
33+
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
34+
with:
35+
generate_release_notes: true
36+
draft: false
37+
prerelease: ${{ contains(github.ref_name, '-') }}

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ Try it:
133133
go run ./example skills print
134134
```
135135

136+
## Releasing
137+
138+
Releases are cut by pushing a semver tag to `main`:
139+
140+
```sh
141+
git tag v0.1.0
142+
git push origin v0.1.0
143+
```
144+
145+
The `Release` workflow verifies the tag lives on `main`, runs the test suite, and drafts a GitHub Release with auto-generated notes. `proxy.golang.org` picks up the tag automatically, so `go get github.com/bueti/skillgen@v0.1.0` works immediately.
146+
147+
Pre-release tags (e.g. `v0.2.0-rc.1`) are marked as pre-releases on GitHub.
148+
136149
## Status
137150

138151
- **M1** — single-skill mode, cobra integration, Claude Code-compatible frontmatter ✅

cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func newGenerateCmd(root *cobra.Command, opts []Option) *cobra.Command {
4444
}
4545
skills, _ := g.Skills()
4646
for _, s := range skills {
47-
fmt.Fprintf(cmd.OutOrStdout(), "wrote %s/%s\n", dir, s.Filename)
47+
cmd.Printf("wrote %s/%s\n", dir, s.Filename)
4848
}
4949
return nil
5050
},

example/main.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package main
77

88
import (
9-
"fmt"
109
"os"
1110

1211
"github.com/bueti/skillgen"
@@ -31,7 +30,7 @@ func main() {
3130
Example: "mytool build api --tag v1.2.3",
3231
Args: cobra.ExactArgs(1),
3332
RunE: func(cmd *cobra.Command, args []string) error {
34-
fmt.Fprintf(cmd.OutOrStdout(), "would build %s\n", args[0])
33+
cmd.Printf("would build %s\n", args[0])
3534
return nil
3635
},
3736
}
@@ -49,7 +48,7 @@ func main() {
4948
},
5049
RunE: func(cmd *cobra.Command, args []string) error {
5150
env, _ := cmd.Flags().GetString("env")
52-
fmt.Fprintf(cmd.OutOrStdout(), "would deploy %s to %s\n", args[0], env)
51+
cmd.Printf("would deploy %s to %s\n", args[0], env)
5352
return nil
5453
},
5554
}
@@ -62,7 +61,7 @@ func main() {
6261
Short: "Show current deployment state",
6362
Args: cobra.ExactArgs(1),
6463
RunE: func(cmd *cobra.Command, args []string) error {
65-
fmt.Fprintf(cmd.OutOrStdout(), "status: %s is healthy\n", args[0])
64+
cmd.Printf("status: %s is healthy\n", args[0])
6665
return nil
6766
},
6867
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/bueti/skillgen
22

3-
go 1.21
3+
go 1.25
44

55
require (
66
github.com/spf13/cobra v1.10.2

0 commit comments

Comments
 (0)