Search code examples
goazure-devopsazure-pipelinesgo-modules

Azure pipeline build go modules correctly


Because the default azure-pipelines.yml template for building go code does not support go modules it is not obvious how it would look like to support it.

This is the default template which is not working for go.modules:

# Go
# Build your Go project.
# Add steps that test, save build artifacts, deploy, and more:
# https://learn.microsoft.com/azure/devops/pipelines/languages/go

trigger:
- master

pool:
  vmImage: ubuntu-latest

variables:
  GOBIN:  '$(GOPATH)/bin' # Go binaries path
  GOROOT: '/usr/local/go1.11' # Go installation path
  GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path
  modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code

steps:
- script: |
    mkdir -p '$(GOBIN)'
    mkdir -p '$(GOPATH)/pkg'
    mkdir -p '$(modulePath)'
    shopt -s extglob
    shopt -s dotglob
    mv !(gopath) '$(modulePath)'
    echo '##vso[task.prependpath]$(GOBIN)'
    echo '##vso[task.prependpath]$(GOROOT)/bin'
  displayName: 'Set up the Go workspace'

- script: |
    go version
    go get -v -t -d ./...
    if [ -f Gopkg.toml ]; then
        curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
        dep ensure
    fi
    go build -v .
  workingDirectory: '$(modulePath)'
  displayName: 'Get dependencies, then build'


Solution

  • I like to share also the answer here for a template that builds a go modules package correctly. Maybe this is just for your inspiration what needs to be considered. It took me some time to get there.

    The main pain point is that the the default template sets the GOPATH to the pipeline workingdirectory which is just wrong if you will download modules via go mod download into it. This would lead to inaccesible files in the next pipeline run, making the pipeline failing during repository checkout.

    The following approach just sets GOPATH to the Agent.HomeDirectory which also makes downloaded modules available for subsequent pipeline runs.

    Maybe it helps someone

    # Go
    # Build your Go project.
    # Add steps that test, save build artifacts, deploy, and more:
    # https://learn.microsoft.com/azure/devops/pipelines/languages/go
    
    trigger: 
    - main
    - feature/*
    
    pool: ubuntu-latest
    
    variables:
      GOPATH: '$(Agent.HomeDirectory)/go' # Go workspace path
      GOBIN:  '$(GOPATH)/bin' # Go binaries path
      GOROOT: '/opt/hostedtoolcache/go/1.15.8/x64' # Go installation path
      
    
    stages:
    - stage: Build
      displayName: Build image
      
      jobs:  
      - job: BuildAndTest
        displayName: Build And Test
        pool: ubuntu-latest
        steps:
        - checkout: self
        - script: |
            export PATH="$(GOROOT)/bin:$(PATH)"
            printenv
            ls -la
            go env
            go version
            go mod download
            go build ./...
            go test ./... 
          workingDirectory: '$(Build.SourcesDirectory)'
          displayName: 'Get dependencies, then build and test'