目次

    GoプロジェクトのためのCI/CDパイプライン設計入門|GitHub ActionsとGitLab CIの実践例
    GoCI/CDGitHub ActionsGitLab CIDevOps自動化

    2025-06-15

    metalpipeline

    GoプロジェクトのためのCI/CDパイプライン設計入門|GitHub ActionsとGitLab CIの実践例

    なぜGoプロジェクトにCI/CDが不可欠なのか?

    Goはコンパイルが速く、シングルバイナリを生成できるため、CI/CDとの相性が抜群です。しかし、手動でのテストやデプロイはヒューマンエラーの原因となり、開発速度を低下させます。品質とスピードを両立させるためには、自動化されたパイプラインが不可欠です。

    特にフリーランスエンジニアにとって、CI/CDの設計・構築スキルは市場価値を大きく左右する重要な要素となっています。クライアント企業は、単にコードを書けるだけでなく、開発プロセス全体を改善できるエンジニアを求めているからです。

    この記事では、GoプロジェクトにおけるCI/CDパイプラインの基本的なステージを解説し、代表的なプラットフォームであるGitHub ActionsとGitLab CIでの実践的な設定ファイルを紹介します。

    GoプロジェクトにおけるCI/CDパイプラインの基本構成

    プラットフォームに依存しない、理想的なパイプラインのステージを解説します。

    1. Setup(セットアップ)

    リポジトリのチェックアウトと適切なGoバージョンの設定を行います。Goのバージョン管理は、プロジェクトの一貫性を保つために重要です。go.modファイルで指定されたバージョンと一致させることで、ローカル環境とCI環境での動作差異を防げます。

    2. Lint & Vet(静的解析)

    go vetによる基本的なチェックに加え、コミュニティ標準のリンターであるgolangci-lintを実行します。golangci-lintgo vetを含む複数のリンターを統合したツールで、コードの一貫性を保ち、潜在的なバグを早期に発見できます。

    以下のような問題を検出します:

    • 未使用の変数や関数
    • 非効率なコード
    • セキュリティ上の問題
    • コーディング規約違反

    3. Test(テスト)

    go test -race -v ./...を実行し、ユニットテストと統合テスト(結合テスト)を実施します。Goの強力な機能であるレースコンディション検出-raceフラグ)を有効にすることで、並行処理における問題を早期に発見できます。

    テストカバレッジの測定も重要です。go test -coverprofile=coverage.out ./...でカバレッジレポートを生成し、テストの品質を可視化しましょう。

    4. Build(ビルド)

    go buildによるコンパイルを実行します。Goの特徴であるクロスコンパイル機能を活用し、複数のプラットフォーム向けのバイナリを生成することも可能です:

    bash
    1GOOS=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の利点により、デプロイメントが大幅に簡素化されます。

    5. Containerize(コンテナ化)

    Dockerイメージのビルドを行います。マルチステージビルドを用いることで、最終的なイメージサイズを最小化し、セキュリティを向上させることができます:

    dockerfile
    1# ビルドステージ
    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"]

    6. Deploy(デプロイ)

    コンテナレジストリ(Docker Hub、GCR、ECR等)へのプッシュと、KubernetesやCloud Runなどの実行環境へのデプロイを行います。

    実践!プラットフォーム別実装例

    GitHub Actions編

    .github/workflows/ci.ymlの完全なサンプルコードです:

    yaml
    1name: 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編

    .gitlab-ci.ymlの完全なサンプルコードです:

    yaml
    1stages:
    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モジュールキャッシュ(GOCACHEGOMODCACHE)を使用する際は、パーミッション周りで失敗する場合があります。必要に応じてchownコマンドでディレクトリの所有者を調整してください。

    セキュリティスキャン

    govulncheck(Go公式の脆弱性スキャナ)やTrivy(コンテナイメージスキャナ)をパイプラインに組み込むことで、セキュリティリスクを早期に発見できます:

    bash
    1# 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を制する者が、開発を制する

    優れたCI/CDパイプラインは、Goプロジェクトの品質と開発速度を飛躍的に向上させます。自動化されたテスト、静的解析、ビルド、デプロイにより、開発者はコードの品質に集中でき、リリースサイクルを加速できます。

    CI/CDの設計・構築スキルは、単にコードを書くだけでなく、開発プロセス全体を改善できる高度なエンジニアであることの証明となります。このスキルセットは、フリーランスエンジニアとしての市場価値を大きく高める要素です。

    私たちGoForceは、このような開発の全体最適化まで視野に入れた高いスキルを持つエンジニアを、正当に評価するクライアント企業と繋いでいます。あなたのCI/CD構築スキルを、次のプロジェクトで活かしませんか。ぜひ一度、私たちにご相談ください。お問い合わせはこちらから。

    会員登録はこちら

    最適なGo案件を今すぐチェック!

    会員登録

    生年月日 *

    /

    /

    Go経験年数 *

    /

    利用規約プライバシーポリシーに同意してお申し込みください。