Skip to content

Commit 765d41a

Browse files
committed
ci: configure release workflow
1 parent 695e721 commit 765d41a

File tree

6 files changed

+281
-6
lines changed

6 files changed

+281
-6
lines changed

.github/workflows/release.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: "Tag to release (e.g., v1.0.0)"
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
release:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0
22+
23+
- name: Set up Go
24+
uses: actions/setup-go@v5
25+
with:
26+
go-version-file: "go.mod"
27+
cache: true
28+
29+
- name: Validate tag format
30+
run: |
31+
if [[ ! "${{ github.event.inputs.tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
32+
echo "Error: Tag must follow semantic versioning (e.g., v1.0.0, v1.0.0-rc1)"
33+
exit 1
34+
fi
35+
36+
- name: Check if tag already exists
37+
run: |
38+
if git tag -l | grep -q "^${{ github.event.inputs.tag }}$"; then
39+
echo "Error: Tag ${{ github.event.inputs.tag }} already exists"
40+
exit 1
41+
fi
42+
43+
- name: Install dependencies
44+
run: go mod download
45+
46+
- name: Check code formatting
47+
run: make format-ci
48+
49+
- name: Run tests
50+
run: make test-ci
51+
52+
- name: Run linters
53+
run: make lint-ci
54+
55+
- name: Create and push tag
56+
run: |
57+
git config user.name "github-actions[bot]"
58+
git config user.email "github-actions[bot]@users.noreply.github.com"
59+
git tag -a "${{ github.event.inputs.tag }}" -m "Release ${{ github.event.inputs.tag }}"
60+
git push origin "${{ github.event.inputs.tag }}"
61+
62+
- name: Run GoReleaser
63+
uses: goreleaser/goreleaser-action@v6
64+
with:
65+
distribution: goreleaser
66+
version: "~> v2"
67+
args: release --clean
68+
env:
69+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.goreleaser.yaml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
project_name: mcp-k8s
2+
3+
before:
4+
hooks:
5+
# You may remove this if you don't use go modules.
6+
- go mod tidy
7+
8+
builds:
9+
- id: mcp-k8s
10+
main: ./cmd/server/main.go
11+
binary: mcp-k8s
12+
goos:
13+
- linux
14+
- windows
15+
- darwin
16+
goarch:
17+
- amd64
18+
- arm64
19+
# Exclude Windows ARM64 as it's not commonly needed
20+
ignore:
21+
- goos: windows
22+
goarch: arm64
23+
env:
24+
- CGO_ENABLED=0
25+
flags:
26+
- -trimpath
27+
ldflags:
28+
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
29+
30+
archives:
31+
- format: tar.gz
32+
# Use zip for Windows archives
33+
format_overrides:
34+
- goos: windows
35+
format: zip
36+
name_template: >-
37+
{{ .ProjectName }}_
38+
{{- title .Os }}_
39+
{{- if eq .Arch "amd64" }}x86_64
40+
{{- else if eq .Arch "386" }}i386
41+
{{- else }}{{ .Arch }}{{ end }}
42+
{{- if .Arm }}v{{ .Arm }}{{ end }}
43+
44+
checksum:
45+
name_template: "checksums.txt"
46+
47+
snapshot:
48+
name_template: "{{ incpatch .Version }}-next"
49+
50+
changelog:
51+
sort: asc
52+
use: github
53+
filters:
54+
exclude:
55+
- "^docs:"
56+
- "^test:"
57+
- "^ci:"
58+
- "^build:"
59+
- "^chore:"
60+
- typo
61+
groups:
62+
- title: "New Features"
63+
regexp: "^.*feat[(\\w)]*:+.*$"
64+
order: 0
65+
- title: "Bug Fixes"
66+
regexp: "^.*fix[(\\w)]*:+.*$"
67+
order: 1
68+
- title: "Refactoring"
69+
regexp: "^.*refactor[(\\w)]*:+.*$"
70+
order: 2
71+
- title: "Documentation"
72+
regexp: "^.*docs[(\\w)]*:+.*$"
73+
order: 3
74+
- title: "Other"
75+
order: 999
76+
77+
release:
78+
# If set to auto, will mark the release as not ready for production
79+
# in case there is an indicator for this in the tag e.g. v1.0.0-rc1
80+
# If set to true, will mark the release as not ready for production.
81+
prerelease: auto
82+
83+
# What to do with the release notes in case there the release already exists.
84+
mode: replace
85+
86+
# Header template for the release body.
87+
header: |
88+
## MCP Kubernetes Server {{ .Tag }}
89+
90+
This release contains the MCP (Model Context Protocol) server for Kubernetes operations.
91+
92+
# Footer template for the release body.
93+
footer: |
94+
## Installation
95+
96+
### Download Binary
97+
Download the appropriate binary for your platform from the assets above.
98+
99+
### macOS/Linux
100+
```bash
101+
# Make executable
102+
chmod +x mcp-k8s
103+
# Move to PATH
104+
sudo mv mcp-k8s /usr/local/bin/
105+
```
106+
107+
### Windows
108+
Add the executable to your PATH or place it in a directory that's already in your PATH.
109+
110+
## Requirements
111+
112+
A kubeconfig providing access to a kubernetes cluster (if you can kubectl you can use this MCP)
113+
114+
## Usage
115+
116+
The MCP server is designed to be used with Claude and other MCP clients:
117+
118+
```bash
119+
# Run the server (communicates via stdio)
120+
mcp-k8s
121+
122+
# Install with Claude Code
123+
claude mcp add k8s mcp-k8s
124+
125+
# Use inspector to browse (requires nodejs)
126+
npx @modelcontextprotocol/inspector mcp-k8s
127+
```
128+
---
129+
**Full Changelog**: https://github.com/krmcbride/mcp-k8s/compare/{{ .PreviousTag }}...{{ .Tag }}
130+
131+
# Disable the release if true.
132+
disable: false
133+

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
- Initial MCP (Model Context Protocol) server implementation for Kubernetes operations
12+
- Kubernetes resource listing with custom formatting (`list_k8s_resources`)
13+
- Kubernetes API resource discovery (`list_k8s_api_resources`)
14+
- Single resource retrieval with Go template support (`get_k8s_resource`)
15+
- CPU/memory metrics for nodes and pods (`get_k8s_metrics`)
16+
- Pod log retrieval (`get_k8s_pod_logs`)
17+
- Kubernetes context discovery via MCP resource (`kubeconfig://contexts`)
18+
- Memory pressure analysis prompt
19+
- Workload instability analysis prompt
20+
- Comprehensive resource mappers for Pods, Deployments, Services, Events, etc.
21+
- Vendor directory for offline development
22+
- GitHub Actions CI pipeline with cross-platform builds
23+
- Automated release workflow with GoReleaser
24+
25+
### Documentation
26+
- Comprehensive CLAUDE.md with modular documentation structure
27+
- Development best practices and guidelines
28+
- CI/CD documentation and patterns
29+
- MCP server development guides
30+
- Kubernetes client architecture documentation
31+
32+
### Development
33+
- Makefile with development, testing, and CI targets
34+
- golangci-lint, gofumpt, and goimports-reviser integration
35+
- Interactive MCP testing with mcptools
36+
- Comprehensive test suite for resource mappers
37+
- Case-insensitive resource kind lookup

CLAUDE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ Each mapper extracts resource-specific fields (e.g., replica counts, status, net
131131
4. Add init() function to register the mapper
132132
5. Update integration test in `integration_test.go`
133133
6. **IMPORTANT**: Update the Resource Mappers list in this documentation
134+
7. **Update `CHANGELOG.md`** under `[Unreleased]` section with the new mapper
134135

135136
## Adding New MCP Tools
136137

@@ -149,6 +150,7 @@ When adding new MCP tools, ensure documentation is updated in both locations:
149150
- Add tool to the Tools section in `README.md` (line ~17)
150151
- Update the Tool Registration section in `CLAUDE.md` (line ~84)
151152
- If adding new client capabilities, update Kubernetes Client Layer section (line ~88)
153+
- **Update `CHANGELOG.md`** under `[Unreleased]` section with the new feature
152154

153155
3. **Validation:**
154156
- Grep for the tool name across documentation files to ensure consistency
@@ -181,4 +183,3 @@ For comprehensive development guidance, see the following detailed guides:
181183
@docs/mcp-server-development.md
182184

183185
@docs/kubernetes-client-architecture.md
184-

cmd/server/main.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ import (
1616
"github.com/krmcbride/mcp-k8s/internal/tools"
1717
)
1818

19+
// Build-time variables set by goreleaser
20+
var (
21+
version = "dev"
22+
commit = "none"
23+
date = "unknown"
24+
)
25+
1926
const (
20-
serverName = "mcp-k8s"
21-
serverVersion = "0.0.0-dev"
27+
serverName = "mcp-k8s"
2228
)
2329

2430
// WARN: only log to stderr to prevent interference with stdio transport
@@ -47,14 +53,16 @@ func main() {
4753
}
4854

4955
if showVersion {
50-
fmt.Printf("%s %s\n", serverName, serverVersion)
56+
fmt.Printf("%s %s\n", serverName, version)
57+
fmt.Printf(" commit: %s\n", commit)
58+
fmt.Printf(" built: %s\n", date)
5159
os.Exit(0)
5260
}
5361

5462
// Initialize the MCP server
5563
s := server.NewMCPServer(
5664
serverName,
57-
serverVersion,
65+
version,
5866
server.WithInstructions(`
5967
This MCP server provides safe, read-only access to Kubernetes clusters through structured tools and resources.
6068
@@ -103,7 +111,7 @@ All tools support CRDs and custom resources automatically through dynamic client
103111

104112
// Start the server in a goroutine
105113
go func() {
106-
fmt.Fprintf(os.Stderr, "Starting MCP server %s %s\n", serverName, serverVersion)
114+
fmt.Fprintf(os.Stderr, "Starting MCP server %s %s\n", serverName, version)
107115
if err := server.ServeStdio(s); err != nil {
108116
errChan <- err
109117
}

docs/ci-best-practices.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,30 @@ strategy:
7676
- `GOFLAGS=""`: CI targets override vendor mode to leverage Go module cache
7777
- Local development still uses `GOFLAGS="-mod=vendor"` for offline builds
7878

79+
## Release Process
80+
81+
**Manual Release Workflow** (`.github/workflows/release.yml`)
82+
83+
- **Trigger**: Manual workflow dispatch with semantic version tag input
84+
- **Pre-release validation**: `make format-ci`, `make test-ci`, `make lint-ci`
85+
- **Tag creation**: Automated git tag creation and push
86+
- **Release automation**: GoReleaser handles cross-platform builds and GitHub release
87+
88+
**Release Checklist:**
89+
90+
1. **Update CHANGELOG.md**:
91+
92+
- Move items from `[Unreleased]` to new version section
93+
- Add release date: `## [1.0.0] - 2025-01-15`
94+
- Create new empty `[Unreleased]` section
95+
96+
2. **Trigger Release**:
97+
98+
- GitHub Actions → "Release" workflow → "Run workflow"
99+
- Enter semantic version tag (e.g., `v1.0.0`)
100+
101+
3. **Post-Release**:
102+
- Verify GitHub release created with binaries
103+
- Update any external documentation if needed
104+
105+
**IMPORTANT**: Always maintain `CHANGELOG.md` manually - GoReleaser only generates GitHub release notes from commits.

0 commit comments

Comments
 (0)