Skip to content

Commit 15e7089

Browse files
authored
Merge pull request #1 from tuannvm/feat/ci-cd
Add CI/CD pipelines and release automation
2 parents 256dbbf + 559c99a commit 15e7089

File tree

9 files changed

+486
-0
lines changed

9 files changed

+486
-0
lines changed

.github/workflows/build.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Build & Test
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
15+
- name: Set up Go
16+
uses: actions/setup-go@v4
17+
with:
18+
go-version: "1.21"
19+
cache: true
20+
21+
- name: Get dependencies
22+
run: go mod download
23+
24+
- name: Build
25+
run: go build -v ./...
26+
27+
- name: Test
28+
run: go test -v ./...

.github/workflows/ci.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
name: Static Analysis
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v3
16+
17+
- name: Set up Go
18+
uses: actions/setup-go@v4
19+
with:
20+
go-version: ">=1.19"
21+
cache: true
22+
23+
- name: Install golangci-lint
24+
uses: golangci/golangci-lint-action@v3
25+
with:
26+
version: latest
27+
args: --timeout=5m
28+
29+
- name: Run golangci-lint
30+
run: golangci-lint run --out-format=colored-line-number
31+
32+
- name: Check Go mod tidy
33+
run: |
34+
go mod tidy
35+
if ! git diff --quiet go.mod go.sum; then
36+
echo "go.mod or go.sum is not tidy, run 'go mod tidy'"
37+
git diff go.mod go.sum
38+
exit 1
39+
fi
40+
41+
build:
42+
name: Build
43+
runs-on: ubuntu-latest
44+
needs: lint
45+
steps:
46+
- name: Checkout code
47+
uses: actions/checkout@v3
48+
49+
- name: Set up Go
50+
uses: actions/setup-go@v4
51+
with:
52+
go-version: ">=1.19"
53+
cache: true
54+
55+
- name: Build
56+
run: go build -v ./...
57+
58+
test:
59+
name: Test
60+
runs-on: ubuntu-latest
61+
needs: build
62+
steps:
63+
- name: Checkout code
64+
uses: actions/checkout@v3
65+
66+
- name: Set up Go
67+
uses: actions/setup-go@v4
68+
with:
69+
go-version: ">=1.19"
70+
cache: true
71+
72+
- name: Run tests
73+
run: go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
74+
75+
- name: Upload coverage reports
76+
uses: codecov/codecov-action@v3
77+
with:
78+
file: ./coverage.txt

.github/workflows/release.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Release
2+
3+
on:
4+
workflow_run:
5+
workflows: ["CI"]
6+
branches: [main]
7+
types:
8+
- completed
9+
10+
permissions:
11+
contents: write # Required for creating GitHub releases
12+
packages: write # Required for pushing to GitHub Container Registry
13+
14+
jobs:
15+
release:
16+
# Only run if the CI workflow was successful
17+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v3
22+
with:
23+
fetch-depth: 0 # Required for version calculation
24+
25+
- name: Set up Go
26+
uses: actions/setup-go@v4
27+
with:
28+
go-version: ">=1.19"
29+
cache: true
30+
31+
- name: Calculate Version
32+
id: calculate_version
33+
run: |
34+
# Start at 1.0.0 if no tags exist
35+
LATEST_TAG=$(git tag -l 'v*' | sort -V | tail -n 1)
36+
if [ -z "$LATEST_TAG" ]; then
37+
NEW_VERSION="1.0.0"
38+
else
39+
# Strip the 'v' prefix
40+
CURRENT_VERSION=${LATEST_TAG#v}
41+
# Split into major, minor, patch
42+
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
43+
# Increment patch version
44+
PATCH=$((PATCH + 1))
45+
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
46+
fi
47+
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
48+
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
49+
echo "Calculated new version: v$NEW_VERSION"
50+
51+
- name: Create Tag
52+
run: |
53+
git config --local user.email "[email protected]"
54+
git config --local user.name "GitHub Action"
55+
git tag -a v${{ steps.calculate_version.outputs.version }} -m "Release v${{ steps.calculate_version.outputs.version }}"
56+
git push origin v${{ steps.calculate_version.outputs.version }}
57+
58+
- name: Login to GitHub Container Registry
59+
uses: docker/login-action@v2
60+
with:
61+
registry: ghcr.io
62+
username: ${{ github.actor }}
63+
password: ${{ secrets.GITHUB_TOKEN }}
64+
65+
- name: Run GoReleaser
66+
uses: goreleaser/goreleaser-action@v4
67+
with:
68+
distribution: goreleaser
69+
version: latest
70+
args: release --clean
71+
env:
72+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
73+
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}

.golangci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
run:
2+
timeout: 5m
3+
4+
linters:
5+
enable:
6+
- errcheck
7+
- gosimple
8+
- govet
9+
- ineffassign
10+
- staticcheck
11+
- typecheck
12+
- unused
13+
- gosec
14+
- revive
15+
- misspell
16+
- gofmt
17+
- goimports
18+
- gocritic
19+
- gocyclo
20+
- bodyclose
21+
- noctx
22+
- unconvert
23+
24+
linters-settings:
25+
gocyclo:
26+
min-complexity: 15
27+
revive:
28+
rules:
29+
- name: exported
30+
gosec:
31+
excludes:
32+
- G204
33+
- G112
34+
gocritic:
35+
enabled-tags:
36+
- diagnostic
37+
- style
38+
- performance
39+
- opinionated
40+
disabled-checks:
41+
- exitAfterDefer
42+
43+
issues:
44+
max-issues-per-linter: 0
45+
max-same-issues: 0
46+
exclude-rules:
47+
- path: _test\.go
48+
linters:
49+
- gosec
50+
- noctx

.goreleaser.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
before:
2+
hooks:
3+
- go mod tidy
4+
5+
builds:
6+
- main: ./cmd/server/main.go
7+
binary: mcp-trino
8+
env:
9+
- CGO_ENABLED=0
10+
goos:
11+
- linux
12+
- darwin
13+
- windows
14+
goarch:
15+
- amd64
16+
- arm64
17+
ldflags:
18+
- -s -w -X main.Version={{.Version}}
19+
20+
archives:
21+
- format: tar.gz
22+
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
23+
format_overrides:
24+
- goos: windows
25+
format: zip
26+
27+
checksum:
28+
name_template: "checksums.txt"
29+
30+
snapshot:
31+
name_template: "{{ .Tag }}-next"
32+
33+
changelog:
34+
sort: asc
35+
filters:
36+
exclude:
37+
- "^docs:"
38+
- "^test:"
39+
- "^chore:"
40+
- "^ci:"
41+
- Merge pull request
42+
- Merge branch
43+
44+
# Explicitly configure GitHub Releases
45+
release:
46+
github:
47+
owner: "{{.Env.GITHUB_REPOSITORY_OWNER}}"
48+
name: "{{.ProjectName}}"
49+
draft: false
50+
prerelease: auto
51+
name_template: "{{.ProjectName}} v{{.Version}}"
52+
53+
dockers:
54+
- image_templates:
55+
- "ghcr.io/{{.Env.GITHUB_REPOSITORY_OWNER}}/mcp-trino:{{ .Version }}"
56+
- "ghcr.io/{{.Env.GITHUB_REPOSITORY_OWNER}}/mcp-trino:latest"
57+
dockerfile: Dockerfile.goreleaser
58+
build_flag_templates:
59+
- "--pull"
60+
- "--label=org.opencontainers.image.created={{.Date}}"
61+
- "--label=org.opencontainers.image.title={{.ProjectName}}"
62+
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
63+
- "--label=org.opencontainers.image.version={{.Version}}"
64+
# Add GitHub Container Registry push configuration
65+
use: docker
66+
push_flags:
67+
- "--tls-verify=false"

Dockerfile.goreleaser

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM alpine:latest
2+
3+
RUN apk --no-cache add ca-certificates
4+
5+
WORKDIR /root/
6+
7+
# Copy the pre-built binary file from the builder stage
8+
COPY mcp-trino .
9+
10+
# Default environment variables
11+
ENV TRINO_HOST="trino"
12+
ENV TRINO_PORT="8080"
13+
ENV TRINO_USER="trino"
14+
ENV TRINO_CATALOG="memory"
15+
ENV TRINO_SCHEMA="default"
16+
ENV MCP_TRANSPORT="http"
17+
ENV MCP_PORT="9097"
18+
19+
# Expose the port
20+
EXPOSE ${MCP_PORT}
21+
22+
# Run the application
23+
ENTRYPOINT ["./mcp-trino"]

Makefile

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
.PHONY: build test clean run-dev release-snapshot run-docker run docker-compose-up docker-compose-down lint
2+
3+
# Variables
4+
BINARY_NAME=mcp-trino
5+
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
6+
BUILD_DIR=bin
7+
8+
# Build the application
9+
build:
10+
mkdir -p $(BUILD_DIR)
11+
go build -ldflags "-X main.Version=$(VERSION)" -o $(BUILD_DIR)/$(BINARY_NAME) ./cmd/server
12+
13+
# Run tests
14+
test:
15+
go test ./...
16+
17+
# Clean build artifacts
18+
clean:
19+
rm -rf $(BUILD_DIR)
20+
21+
# Run the application in development mode
22+
run-dev:
23+
go run cmd/server/main.go
24+
25+
# Create a release snapshot using GoReleaser
26+
release-snapshot:
27+
goreleaser release --snapshot --clean
28+
29+
# Run the application using the built binary
30+
run:
31+
./$(BUILD_DIR)/$(BINARY_NAME)
32+
33+
# Build and run Docker image
34+
run-docker: build
35+
docker build -t $(BINARY_NAME):$(VERSION) .
36+
docker run -p 9097:9097 $(BINARY_NAME):$(VERSION)
37+
38+
# Start the application with Docker Compose
39+
docker-compose-up:
40+
docker-compose up -d
41+
42+
# Stop Docker Compose services
43+
docker-compose-down:
44+
docker-compose down
45+
46+
# Run linting checks (same as CI)
47+
lint:
48+
@echo "Running linters..."
49+
@go mod tidy
50+
@if ! git diff --quiet go.mod go.sum; then echo "go.mod or go.sum is not tidy, run 'go mod tidy'"; git diff go.mod go.sum; exit 1; fi
51+
@if ! command -v golangci-lint &> /dev/null; then echo "Installing golangci-lint..." && go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest; fi
52+
@golangci-lint run --timeout=5m
53+
54+
# Default target
55+
all: clean build

0 commit comments

Comments
 (0)