Initial work on a new package build process

For the moment this is just an experimental additional sidecar package
build process, separate from the one we really use for releases, so that
we can get some experience building in the GitHub Actions environment
before hopefully eventually switching to using the artifacts from this
process as the packages we'll release through the official release
channels.

It will react to any push to one of our release branches or to a release
tag by building official-release-like .zip, .deb, and .rpm packages, along
with Docker images, based on the content of the corresponding commit.

For the moment this doesn't actually produce _shippable_ packages because
in particular it doesn't know how to update our version/version.go file
to hard-code the correct version number. Once Go 1.18 is release and we've
upgraded to it we'll switch to using debug.ReadBuildInfo to determine
our version number at runtime and so no longer need to directly update
a source file for each release, but that functionality isn't yet available
in our current Go 1.17 release.
This commit is contained in:
Martin Atkins 2021-12-22 16:47:15 -08:00
parent 535da4ebc7
commit 6704f8c795
2 changed files with 250 additions and 0 deletions

41
.github/workflows/build-Dockerfile vendored Normal file
View File

@ -0,0 +1,41 @@
# This Dockerfile is not intended for general use, but is rather used to
# produce our "light" release packages as part of our official release
# pipeline.
#
# If you want to test this locally you'll need to set the three arguments
# to values realistic for what the hashicorp/actions-docker-build GitHub
# action would set, and ensure that there's a suitable "terraform" executable
# in the dist/linux/${TARGETARCH} directory.
FROM docker.mirror.hashicorp.services/alpine:latest AS default
# This is intended to be run from the hashicorp/actions-docker-build GitHub
# action, which sets these appropriately based on context.
ARG PRODUCT_VERSION=UNSPECIFIED
ARG PRODUCT_REVISION=UNSPECIFIED
ARG BIN_NAME=terraform
# This argument is set by the Docker toolchain itself, to the name
# of the CPU architecture we're building an image for.
# Our caller should've extracted the corresponding "terraform" executable
# into dist/linux/${TARGETARCH} for us to use.
ARG TARGETARCH
LABEL maintainer="HashiCorp Terraform Team <terraform@hashicorp.com>"
# New standard version label.
LABEL version=$VERSION
# Historical Terraform-specific label preserved for backward compatibility.
LABEL "com.hashicorp.terraform.version"="${VERSION}"
RUN apk add --no-cache git openssh
# The hashicorp/actions-docker-build GitHub Action extracts the appropriate
# release package for our target architecture into the current working
# directory before running "docker build", which we'll then copy into the
# Docker image to make sure that we use an identical binary as all of the
# other official release channels.
COPY ["dist/linux/${TARGETARCH}/terraform", "/bin/terraform"]
ENTRYPOINT ["/bin/terraform"]

209
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,209 @@
name: Build Terraform CLI Packages
# If you want to test changes to this file before merging to a main branch,
# push them up to a branch whose name has the prefix "build-workflow-dev/",
# which is a special prefix that triggers this workflow even though it's not
# actually a release branch.
on:
workflow_dispatch:
push:
branches:
- main
- 'v[0-9]+.[0-9]+'
- build-workflow-dev/*
tags:
- 'v[0-9]+.[0-9]+.[0-9]+*'
env:
PKG_NAME: "terraform"
jobs:
get-product-version:
name: "Determine intended Terraform version"
runs-on: ubuntu-latest
outputs:
product-version: ${{ steps.get-product-version.outputs.product-version }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Need all commits and tags to find a reasonable version number
- name: Decide version number
id: get-product-version
run: |
git describe --first-parent
echo "::set-output name=product-version::$(git describe --first-parent)"
get-go-version:
name: "Determine Go toolchain version"
runs-on: ubuntu-latest
outputs:
go-version: ${{ steps.get-go-version.outputs.go-version }}
steps:
- uses: actions/checkout@v2
- name: Determine Go version
id: get-go-version
# We use .go-version as our source of truth for current Go
# version, because "goenv" can react to it automatically.
run: |
echo "Building with Go $(cat .go-version)"
echo "::set-output name=go-version::$(cat .go-version)"
generate-metadata-file:
name: "Generate release metadata"
needs: get-product-version
runs-on: ubuntu-latest
outputs:
filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
steps:
- uses: actions/checkout@v2
- name: Generate package metadata
id: generate-metadata-file
uses: hashicorp/actions-generate-metadata@main
with:
version: ${{ needs.get-product-version.outputs.product-version }}
product: ${{ env.PKG_NAME }}
- uses: actions/upload-artifact@v2
with:
name: metadata.json
path: ${{ steps.generate-metadata-file.outputs.filepath }}
build:
needs: ["get-product-version", "get-go-version"]
runs-on: ubuntu-latest
strategy:
matrix:
include:
- {goos: "freebsd", goarch: "386"}
- {goos: "freebsd", goarch: "amd64"}
- {goos: "freebsd", goarch: "arm"}
- {goos: "linux", goarch: "386"}
- {goos: "linux", goarch: "amd64"}
- {goos: "linux", goarch: "arm"}
- {goos: "linux", goarch: "arm64"}
- {goos: "openbsd", goarch: "386"}
- {goos: "openbsd", goarch: "amd64"}
- {goos: "solaris", goarch: "amd64"}
- {goos: "windows", goarch: "386"}
- {goos: "windows", goarch: "amd64"}
fail-fast: false
name: Build for ${{ matrix.goos }}_${{ matrix.goarch }}
steps:
- uses: actions/checkout@v2
- name: Install Go toolchain
uses: actions/setup-go@v2
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- name: Build
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
mkdir dist out
go build -o dist/ .
zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/
- uses: actions/upload-artifact@v2
with:
name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
path: out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
- name: Linux distribution packages
if: ${{ matrix.goos == 'linux' }}
uses: hashicorp/package@v1
with:
name: "terraform"
description: "Terraform enables you to safely and predictably create, change, and improve infrastructure. It is an open source tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned."
arch: ${{ matrix.goarch }}
version: ${{ needs.get-product-version.outputs.product-version }}
maintainer: "HashiCorp"
homepage: "https://terraform.io/"
license: "MPL-2.0"
binary: "dist/${{ env.PKG_NAME }}"
deb_depends: "git"
rpm_depends: "git"
- name: Gather Linux distribution package filenames
if: ${{ matrix.goos == 'linux' }}
run: |
echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
- uses: actions/upload-artifact@v2
if: ${{ matrix.goos == 'linux' }}
with:
name: ${{ env.RPM_PACKAGE }}
path: out/${{ env.RPM_PACKAGE }}
- uses: actions/upload-artifact@v2
if: ${{ matrix.goos == 'linux' }}
with:
name: ${{ env.DEB_PACKAGE }}
path: out/${{ env.DEB_PACKAGE }}
build-darwin:
needs: ["get-product-version", "get-go-version"]
runs-on: macos-latest
strategy:
matrix:
include:
- {goos: "darwin", goarch: "amd64"}
- {goos: "darwin", goarch: "arm64"}
fail-fast: false
name: Build for ${{ matrix.goos }}_${{ matrix.goarch }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
steps:
- uses: actions/checkout@v2
- name: Install Go toolchain
uses: actions/setup-go@v2
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- name: Build
run: |
mkdir dist out
go build -o dist/
zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/
- uses: actions/upload-artifact@v2
with:
name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
path: out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
build-docker:
name: Build Docker image for linux_${{ matrix.arch }}
needs:
- get-product-version
- build
runs-on: ubuntu-latest
strategy:
matrix:
arch: ["amd64"]
fail-fast: false
env:
repo: ${{github.event.repository.name}}
version: ${{needs.get-product-version.outputs.product-version}}
steps:
- uses: actions/checkout@v2
- name: Build Docker images
uses: hashicorp/actions-docker-build@v1
with:
version: ${{env.version}}
target: default
arch: ${{matrix.arch}}
dockerfile: .github/workflows/build-Dockerfile
tags: |
docker.io/hashicorp/${{env.repo}}:${{env.version}}
986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{env.repo}}:${{env.version}}