2025-06-15
Goはコンパイルが速く、シングルバイナリを生成できるため、CI/CDとの相性が抜群です。しかし、手動でのテストやデプロイはヒューマンエラーの原因となり、開発速度を低下させます。品質とスピードを両立させるためには、自動化されたパイプラインが不可欠です。
特にフリーランスエンジニアにとって、CI/CDの設計・構築スキルは市場価値を大きく左右する重要な要素となっています。クライアント企業は、単にコードを書けるだけでなく、開発プロセス全体を改善できるエンジニアを求めているからです。
この記事では、GoプロジェクトにおけるCI/CDパイプラインの基本的なステージを解説し、代表的なプラットフォームであるGitHub ActionsとGitLab CIでの実践的な設定ファイルを紹介します。
プラットフォームに依存しない、理想的なパイプラインのステージを解説します。
リポジトリのチェックアウトと適切なGoバージョンの設定を行います。Goのバージョン管理は、プロジェクトの一貫性を保つために重要です。go.mod
ファイルで指定されたバージョンと一致させることで、ローカル環境とCI環境での動作差異を防げます。
go vet
による基本的なチェックに加え、コミュニティ標準のリンターであるgolangci-lint
を実行します。golangci-lint
はgo vet
を含む複数のリンターを統合したツールで、コードの一貫性を保ち、潜在的なバグを早期に発見できます。
以下のような問題を検出します:
go test -race -v ./...
を実行し、ユニットテストと統合テスト(結合テスト)を実施します。Goの強力な機能であるレースコンディション検出(-race
フラグ)を有効にすることで、並行処理における問題を早期に発見できます。
テストカバレッジの測定も重要です。go test -coverprofile=coverage.out ./...
でカバレッジレポートを生成し、テストの品質を可視化しましょう。
go build
によるコンパイルを実行します。Goの特徴であるクロスコンパイル機能を活用し、複数のプラットフォーム向けのバイナリを生成することも可能です:
bash1GOOS=linux GOARCH=amd64 go build -o app-linux-amd64 2GOOS=windows GOARCH=amd64 go build -o app-windows-amd64.exe 3GOOS=darwin GOARCH=arm64 go build -o app-darwin-arm64
※Windows環境では、PowerShellで$env:GOOS="linux"
のように環境変数を設定するか、go-cross
などのツールを使用してください。
シングルバイナリが生成されるGoの利点により、デプロイメントが大幅に簡素化されます。
Dockerイメージのビルドを行います。マルチステージビルドを用いることで、最終的なイメージサイズを最小化し、セキュリティを向上させることができます:
dockerfile1# ビルドステージ 2 3FROM golang:1.22-alpine AS builder 4WORKDIR /app 5COPY go.mod go.sum ./ 6RUN go mod download 7COPY . . 8RUN CGO_ENABLED=0 GOOS=linux go build -o main . 9 10# 実行ステージ 11 12FROM alpine:latest 13RUN apk --no-cache add ca-certificates 14WORKDIR /root/ 15COPY --from=builder /app/main . 16CMD ["./main"]
コンテナレジストリ(Docker Hub、GCR、ECR等)へのプッシュと、KubernetesやCloud Runなどの実行環境へのデプロイを行います。
.github/workflows/ci.yml
の完全なサンプルコードです:
yaml1name: CI/CD Pipeline 2 3on: 4 push: 5 branches: [ main, develop ] 6 pull_request: 7 branches: [ main ] 8 9jobs: 10 test: 11 runs-on: ubuntu-latest 12 13 steps: 14 - uses: actions/checkout@v4 15 16 - name: Set up Go 17 uses: actions/setup-go@v5 18 with: 19 go-version: '1.22' 20 21 - name: Cache Go modules 22 uses: actions/cache@v4 23 with: 24 path: ~/go/pkg/mod 25 key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 26 restore-keys: | 27 ${{ runner.os }}-go- 28 29 - name: Install dependencies 30 run: go mod download 31 32 - name: Run golangci-lint 33 uses: golangci/golangci-lint-action@v4 34 with: 35 version: latest 36 37 - name: Run tests 38 run: go test -race -coverprofile=coverage.out -v ./... 39 40 - name: Upload coverage to Codecov 41 uses: codecov/codecov-action@v4 42 with: 43 files: coverage.out 44 45 - name: Build 46 run: go build -v ./... 47 48 - name: Build Docker image 49 run: docker build -t myapp:${{ github.sha }} . 50 51 - name: Log in to registry 52 if: github.ref == 'refs/heads/main' 53 run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USER }}" --password-stdin 54 55 - name: Push Docker image 56 if: github.ref == 'refs/heads/main' 57 run: docker push myapp:${{ github.sha }} 58 59 - name: Set up kubectl 60 if: github.ref == 'refs/heads/main' 61 uses: azure/setup-kubectl@v3 62 63 - name: Deploy to Kubernetes 64 if: github.ref == 'refs/heads/main' 65 run: | 66 kubectl set image deployment/myapp myapp=myapp:${{ github.sha }} 67 kubectl apply -f ./k8s/deployment.yaml
.gitlab-ci.yml
の完全なサンプルコードです:
yaml1stages: 2 - test 3 - build 4 - deploy 5 6variables: 7 GO_VERSION: "1.22" 8 9cache: 10 paths: 11 - .cache/go-build/ 12 - .cache/go-mod/ 13 14before_script: 15 - mkdir -p .cache/go-build .cache/go-mod 16 - export GOCACHE=$PWD/.cache/go-build 17 - export GOMODCACHE=$PWD/.cache/go-mod 18 19test: 20 stage: test 21 image: golang:${GO_VERSION} 22 script: 23 - go mod download 24 - go vet ./... 25 - go test -race -coverprofile=coverage.out -v ./... 26 - go install github.com/boumenot/gocover-cobertura@latest 27 - gocover-cobertura < coverage.out > coverage.xml 28 artifacts: 29 reports: 30 coverage_report: 31 coverage_format: cobertura 32 path: coverage.xml 33 paths: 34 - coverage.out 35 expire_in: 1 week 36 37lint: 38 stage: test 39 image: golangci/golangci-lint:latest 40 script: 41 - golangci-lint run 42 43build: 44 stage: build 45 image: golang:${GO_VERSION} 46 script: 47 - go build -o app . 48 artifacts: 49 paths: 50 - app 51 expire_in: 1 week 52 53docker-build: 54 stage: build 55 image: docker:latest 56 services: 57 - docker:dind 58 script: 59 - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY 60 - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . 61 - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA 62 only: 63 - main
Goモジュールのキャッシュを適切に設定することで、パイプラインの実行時間を大幅に短縮できます。GitHub Actionsではactions/cache
、GitLab CIではcache
ディレクティブを活用しましょう。
※GitLab CIでGoモジュールキャッシュ(GOCACHE
・GOMODCACHE
)を使用する際は、パーミッション周りで失敗する場合があります。必要に応じてchown
コマンドでディレクトリの所有者を調整してください。
govulncheck
(Go公式の脆弱性スキャナ)やTrivy
(コンテナイメージスキャナ)をパイプラインに組み込むことで、セキュリティリスクを早期に発見できます:
bash1# Go依存関係の脆弱性スキャン(JSON出力でアーティファクト保存) 2 3go install golang.org/x/vuln/cmd/govulncheck@latest 4govulncheck -json ./... > govuln.json 5 6# ソースコードの脆弱性スキャン 7 8trivy fs --format json . > trivy-fs.json 9 10# コンテナイメージの脆弱性スキャン 11 12trivy image --format json myapp:${{ github.sha }} > trivy-img.json
JSON形式で出力することで、後続の自動評価や可視化ツールとの連携が容易になります。
優れたCI/CDパイプラインは、Goプロジェクトの品質と開発速度を飛躍的に向上させます。自動化されたテスト、静的解析、ビルド、デプロイにより、開発者はコードの品質に集中でき、リリースサイクルを加速できます。
CI/CDの設計・構築スキルは、単にコードを書くだけでなく、開発プロセス全体を改善できる高度なエンジニアであることの証明となります。このスキルセットは、フリーランスエンジニアとしての市場価値を大きく高める要素です。
私たちGoForceは、このような開発の全体最適化まで視野に入れた高いスキルを持つエンジニアを、正当に評価するクライアント企業と繋いでいます。あなたのCI/CD構築スキルを、次のプロジェクトで活かしませんか。ぜひ一度、私たちにご相談ください。お問い合わせはこちらから。
最適なGo案件を今すぐチェック!