multi os binary build

setup gox

gox라는 명령어를 이용할 것이다.

Gox - Simple Go Cross Compilation

다음 웹사이트를 참고하자.

https://github.com/mitchellh/gox

project 폴더에서 다음을 실행한다.

go get github.com/mitchellh/gox@v1.0.1

go.mod에 내용이 추가된걸 확인할수 있다.

이제 ci/cd시에 이 프로젝트를 설치하게 해주면된다.

tools.go 추가

vi tools.go

//go:build tools
// +build tools

package main

// These imports are to force `go mod tidy` not to remove that tools we depend
// on development. This is explained in great detail in
// https://marcofranssen.nl/manage-go-tools-via-go-modules/
import (
  _ "github.com/mitchellh/gox"
)

build

make 파일을 사용해서 빌드를 해보자.

프로젝트에 Makefile을 만들자.

vi Makefile

PROJECT_NAME := jiractl

.PHONY: setup clean build-binaries
setup: clean
 $Q mkdir -p bin/
 $Q go mod tidy
# From https://marcofranssen.nl/manage-go-tools-via-go-modules/
 @cat tools.go | \
  grep _ | \
  awk -F'"' '{print $$2}' | \
  GOBIN=$(CURDIR)/bin xargs -tI % go install %

clean:
 $Q rm -rf bin/*

BUILD_PLATFORMS ?= -os '!netbsd' -os '!openbsd'

build-binaries: setup
 # Building $(PROJECT_NAME) for $(BUILD_PLATFORMS)
 ${CURDIR}/bin/gox $(BUILD_PLATFORMS) \
  -output="bin/binaries/$(PROJECT_NAME)-{{.OS}}-{{.Arch}}" .

clean -> setup -> build-binaries 로 동작한다.

make build-binaries를 하면 패키지를 빌드한다.

ci/cd setup

.gitlab-ci.yml

variables:
  GO_VERSION: '1.18.5'
  # See https://docs.gitlab.com/ee/user/packages/generic_packages/#publish-a-package-file
  PACKAGE_REGISTRY_URL: '$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jiractl'

image: golang:${GO_VERSION}

.binaries: &binaries
  image: golang:1.18
  rules:
    - if: '$CI_COMMIT_TAG'
  stage: build
  script:
    - export platforms=$(echo $CI_JOB_NAME | sed 's|binaries ||')
    - make build-binaries BUILD_PLATFORMS="-osarch='$platforms'"
  artifacts:
    paths:
      - app/bin/binaries
    expire_in: 7d

binaries darwin/amd64: *binaries
binaries darwin/arm64: *binaries
binaries freebsd/386 freebsd/amd64 freebsd/arm: *binaries
binaries linux/386 linux/amd64 linux/arm linux/arm64 linux/ppc64le: *binaries
binaries windows/386 windows/amd64:
  extends: .binaries

yaml yank를 이용해서 yaml을 줄엿다. 기본적으로는 *binaries에 위에 binary를 다 넣어주면 된다.

binaries darwin/amd64 이게 작업 이름인데 이것중요 darwin/amd64를 가져와서 그걸 make에 보내주면 make가 빌드를 하는 구조이다.

artifact를 이용하여 저장을 해두는것이다. 이렇게 해두면 ui에서 다운로드를 받을수 있다.

upload artifact to package & registries

vi .gitlab-ci.yml

upload binaries to generic package for tag:
  stage: publish
  image: curlimages/curl:latest
  needs:
    - 'binaries darwin/amd64'
    - 'binaries darwin/arm64'
    - 'binaries freebsd/386 freebsd/amd64 freebsd/arm'
    - 'binaries linux/386 linux/amd64 linux/arm linux/arm64 linux/ppc64le'
    - 'binaries windows/386 windows/amd64'
  rules:
    - if: '$CI_COMMIT_TAG'
  script:
    - cd app/bin/binaries/
    - |
      for FILE in *; do
        curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ${FILE} ${PACKAGE_REGISTRY_URL}/${CI_COMMIT_TAG}/${FILE} ;
      done

아까 설정해둔 variable 을 사용한다.

PACKAGE_REGISTRY_URL: '$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jiractl'

for문을 돌면서 파일을 업로드한다.

실행하면 다음과 같이 패키지에 업로드 됨을 알수있다.

release

vi .gitlab-ci.yml

일단 git에 로그를 읽어와서 description이라는 환경변수 사용해야하므로 파일에 적어둔후 artifact에 추가해준다. 나중에 $DESCRIPTION 이러면 다른 작업에서 사용할수 있다.

generate_description:
  # generate_description needs to run in a previous stage before release
  stage: publish
  rules:
    - if: '$CI_COMMIT_TAG'
  script:
    # generate description from annotated tag's subject
    - echo "DESCRIPTION=$(git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:'At %ci, %cN committed %h - %s' --decorate --graph)" > description.env
    - cat description.env
  artifacts:
    reports:
      dotenv: description.env

이제 release를 생성하자 file은 링크로 잡아서 올려주면 된다.

release-from-tag:
  image: registry.gitlab.com/gitlab-org/release-cli
  stage: release
  needs:
    - 'upload binaries to generic package for tag'
    - 'generate_description'
  rules:
    - if: '$CI_COMMIT_TAG' # Run this job when a tag is created manually
  script:
    - echo "Creating a release for $CI_COMMIT_TAG"
    - echo "$DESCRIPTION"
  release:
    name: 'Release $CI_COMMIT_TAG'
    description: '$DESCRIPTION'
    tag_name: '$CI_COMMIT_TAG'
    ref: '$CI_COMMIT_TAG'
    assets:
      links:
        - name: 'darwin/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-darwin-amd64'
          filepath: '/app/bin/binaries/jiractl-darwin-amd64'
        - name: 'darwin/arm64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-darwin-arm64'
          filepath: '/app/bin/binaries/jiractl-darwin-arm64'
        - name: 'freebsd/386'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-freebsd-386'
          filepath: '/app/bin/binaries/jiractl-freebsd-386'
        - name: 'freebsd/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-freebsd-amd64'
          filepath: '/app/bin/binaries/jiractl-freebsd-amd64'
        - name: 'freebsd/arm'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-freebsd-arm'
          filepath: '/app/bin/binaries/jiractl-freebsd-arm'
        - name: 'linux/386'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-386'
          filepath: '/app/bin/binaries/jiractl-linux-386'
        - name: 'linux/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-amd64'
          filepath: '/app/bin/binaries/jiractl-linux-amd64'
        - name: 'linux/arm'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-arm'
          filepath: '/app/bin/binaries/jiractl-linux-arm'
        - name: 'linux/arm64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-arm64'
          filepath: '/app/bin/binaries/jiractl-linux-arm64'
        - name: 'linux/ppc64le'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-ppc64le'
          filepath: '/app/bin/binaries/jiractl-linux-ppc64le'
        - name: 'windows/386'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-windows-386.exe'
          filepath: '/app/bin/binaries/jiractl-windows-386.exe'
        - name: 'windows/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-windows-amd64.exe'
          filepath: '/app/bin/binaries/jiractl-windows-amd64.exe'

다음처럼 release가 생긴것을 알수 있다.

완성

Last updated

Was this helpful?