From ff37be59a8364c784b6be9a50cf48b49d2679fbe Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 18 May 2022 16:58:10 -0700 Subject: [PATCH 1/3] build: Fetch all tags before deciding which version we're building The actions/checkout workflow does some heroics to try to fetch exactly the commit being built and nothing else, even if asked to fetch the history leading up to that commit. That means we don't end up having enough information to get an accurate answer from "git describe". Since we're intentionally relying on the git history here, we'll fetch all of the tags explicitly after initial checkout. Although that does add some delay to this step, we're intentionally doing this version calculation only once as a separate workflow job so that all of the other jobs can still benefit from this action's quicker checkout behavior. --- .github/workflows/build.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d423829008c7..af6aa9db83ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,13 +44,17 @@ jobs: 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 + - uses: actions/checkout@v3 - name: Git Describe id: git-describe run: | - git describe --first-parent + # The actions/checkout action tries hard to fetch as little as + # possible, to the extent that even with "depth: 0" it fails to + # produce enough tag metadata for us to "describe" successfully. + # We'll therefore re-fetch the tags here to make sure we will + # select the most accurate version number. + git fetch origin --force --tags + git tag echo "::set-output name=raw-version::$(git describe --first-parent)" - name: Decide version number id: get-product-version @@ -58,6 +62,7 @@ jobs: env: RAW_VERSION: ${{ steps.git-describe.outputs.raw-version }} run: | + echo "Version number is ${RAW_VERSION}" echo "::set-output name=product-version::${RAW_VERSION#v}" - name: Report chosen version number run: | From f6144e6d9155a5a6831f717346707f21941fa3fa Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 19 May 2022 12:05:22 -0700 Subject: [PATCH 2/3] build: Write the detected version number into the generated executable This also sets an additional variable if it detects that this is an alpha or development build, which currently does nothing but might eventually turn on the ability to use experimental features, if we make that something available only in prereleases. --- .github/workflows/build.yml | 86 +++++++++++++++++++++--- internal/command/e2etest/make-archive.sh | 9 ++- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index af6aa9db83ab..ae88a7fe2687 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,6 +42,10 @@ jobs: runs-on: ubuntu-latest outputs: product-version: ${{ steps.get-product-version.outputs.product-version }} + product-version-base: ${{ steps.get-product-version.outputs.product-version-base }} + product-version-pre: ${{ steps.get-product-version.outputs.product-version-pre }} + experiments: ${{ steps.get-product-version.outputs.experiments }} + go-ldflags: ${{ steps.get-product-version.outputs.go-ldflags }} steps: - uses: actions/checkout@v3 @@ -53,17 +57,60 @@ jobs: # produce enough tag metadata for us to "describe" successfully. # We'll therefore re-fetch the tags here to make sure we will # select the most accurate version number. - git fetch origin --force --tags - git tag - echo "::set-output name=raw-version::$(git describe --first-parent)" + git fetch origin --force --tags --quiet --unshallow + git log --tags --simplify-by-decoration --decorate-refs='refs/tags/v*' --pretty=format:'%h %<|(35)%S %ci' --max-count 15 --topo-order + set -e + RAW_VERSION=$(git describe --tags --match='v*' ${GITHUB_SHA}) + echo " + + Raw version is ${RAW_VERSION}" + echo "::set-output name=raw-version::${RAW_VERSION}" - name: Decide version number id: get-product-version shell: bash env: RAW_VERSION: ${{ steps.git-describe.outputs.raw-version }} run: | - echo "Version number is ${RAW_VERSION}" - echo "::set-output name=product-version::${RAW_VERSION#v}" + # Trim the "v" prefix, if any. + VERSION="${RAW_VERSION#v}" + + # Split off the build metadata part, if any + # (we won't actually include it in our final version, and handle it only for + # compleness against semver syntax.) + IFS='+' read -ra BUILD_METADATA_PARTS <<< "$VERSION" + VERSION="${BUILD_METADATA_PARTS[0]}" + BUILD_META="${BUILD_METADATA_PARTS[1]}" + + # Separate out the prerelease part, if any + # (version.go expects it to be in a separate variable) + IFS='-' read -ra PRERELEASE_PARTS <<< "$VERSION" + BASE_VERSION="${PRERELEASE_PARTS[0]}" + PRERELEASE="${PRERELEASE_PARTS[1]}" + + EXPERIMENTS_ENABLED=0 + if [[ "$PRERELEASE" == alpha* ]]; then + EXPERIMENTS_ENABLED=1 + fi + if [[ "$PRERELEASE" == dev* ]]; then + EXPERIMENTS_ENABLED=1 + fi + + LDFLAGS="-w -s" + if [[ "$EXPERIMENTS_ENABLED" == 1 ]]; then + LDFLAGS="${LDFLAGS} -X 'main.experimentsAllowed=yes'" + fi + LDFLAGS="${LDFLAGS} -X 'github.com/hashicorp/terraform/version.Version=${BASE_VERSION}'" + LDFLAGS="${LDFLAGS} -X 'github.com/hashicorp/terraform/version.Prerelease=${PRERELEASE}'" + + echo "Building Terraform CLI ${VERSION}" + if [[ "$EXPERIMENTS_ENABLED" == 1 ]]; then + echo "This build allows use of experimental features" + fi + echo "::set-output name=product-version::${VERSION}" + echo "::set-output name=product-version-base::${BASE_VERSION}" + echo "::set-output name=product-version-pre::${PRERELEASE}" + echo "::set-output name=experiments::${EXPERIMENTS_ENABLED}" + echo "::set-output name=go-ldflags::${LDFLAGS}" - name: Report chosen version number run: | [ -n "${{steps.get-product-version.outputs.product-version}}" ] @@ -127,6 +174,13 @@ jobs: - {goos: "darwin", goarch: "arm64", runson: "macos-latest"} fail-fast: false + env: + FULL_VERSION: ${{ needs.get-product-version.outputs.product-version }} + BASE_VERSION: ${{ needs.get-product-version.outputs.product-version-base }} + VERSION_PRERELEASE: ${{ needs.get-product-version.outputs.product-version-pre }} + EXPERIMENTS_ENABLED: ${{ needs.get-product-version.outputs.experiments }} + GO_LDFLAGS: ${{ needs.get-product-version.outputs.go-ldflags }} + steps: - uses: actions/checkout@v2 @@ -159,13 +213,14 @@ jobs: # cross-build for darwin_arm64.) export CGO_ENABLED=1 fi - go build -ldflags "-w -s" -o dist/ . - zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ + set -x + go build -ldflags "${GO_LDFLAGS}" -o dist/ . + zip -r -j out/${{ env.PKG_NAME }}_${FULL_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: ${{ env.PKG_NAME }}_${{ env.FULL_VERSION }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + path: out/${{ env.PKG_NAME }}_${{ env.FULL_VERSION }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip package-linux: name: "Build Linux distro packages for ${{ matrix.arch }}" @@ -252,7 +307,7 @@ jobs: fail-fast: false env: - repo: ${{github.event.repository.name}} + repo: "terraform" version: ${{needs.get-product-version.outputs.product-version}} steps: @@ -260,7 +315,9 @@ jobs: - name: Build Docker images uses: hashicorp/actions-docker-build@v1 with: + pkg_name: "terraform_${{env.version}}" version: ${{env.version}} + bin_name: terraform target: default arch: ${{matrix.arch}} dockerfile: .github/workflows/build-Dockerfile @@ -271,7 +328,9 @@ jobs: e2etest-build: name: Build e2etest for ${{ matrix.goos }}_${{ matrix.goarch }} runs-on: ubuntu-latest - needs: ["get-go-version"] + needs: + - get-product-version + - get-go-version strategy: matrix: # We build test harnesses only for the v1.0 Compatibility Promises @@ -306,7 +365,12 @@ jobs: env: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} + GO_LDFLAGS: ${{ needs.get-product-version.outputs.go-ldflags }} run: | + # NOTE: This script reacts to the GOOS, GOARCH, and GO_LDFLAGS + # environment variables defined above. The e2e test harness + # needs to know the version we're building for so it can verify + # that "terraform version" is returning that version number. bash ./internal/command/e2etest/make-archive.sh - uses: actions/upload-artifact@v2 diff --git a/internal/command/e2etest/make-archive.sh b/internal/command/e2etest/make-archive.sh index 040633b5dd9a..b88078a97c61 100755 --- a/internal/command/e2etest/make-archive.sh +++ b/internal/command/e2etest/make-archive.sh @@ -31,13 +31,20 @@ GOEXE="$(go env GOEXE)" OUTDIR="build/${GOOS}_${GOARCH}" OUTFILE="terraform-e2etest_${GOOS}_${GOARCH}.zip" +LDFLAGS="-X github.com/hashicorp/terraform/internal/command/e2etest.terraformBin=./terraform$GOEXE" +# Caller may pass in the environment variable GO_LDFLAGS with additional +# flags we'll use when building. +if [ -n "${GO_LDFLAGS+set}" ]; then + LDFLAGS="${GO_LDFLAGS} ${LDFLAGS}" +fi + mkdir -p "$OUTDIR" # We need the test fixtures available when we run the tests. cp -r testdata "$OUTDIR/testdata" # Build the test program -go test -o "$OUTDIR/e2etest$GOEXE" -c -ldflags "-X github.com/hashicorp/terraform/internal/command/e2etest.terraformBin=./terraform$GOEXE" github.com/hashicorp/terraform/internal/command/e2etest +go test -o "$OUTDIR/e2etest$GOEXE" -c -ldflags "$LDFLAGS" github.com/hashicorp/terraform/internal/command/e2etest # Now bundle it all together for easy shipping! cd "$OUTDIR" From 24e5331d31aad6da5d399fa43b31528a36b1332e Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 19 May 2022 16:51:54 -0700 Subject: [PATCH 3/3] build: Accept version numbers with prereleases containing dashes Previously we'd discard everything after the second dash. --- .github/workflows/build.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ae88a7fe2687..ee68fec8cac8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,15 +77,11 @@ jobs: # Split off the build metadata part, if any # (we won't actually include it in our final version, and handle it only for # compleness against semver syntax.) - IFS='+' read -ra BUILD_METADATA_PARTS <<< "$VERSION" - VERSION="${BUILD_METADATA_PARTS[0]}" - BUILD_META="${BUILD_METADATA_PARTS[1]}" + IFS='+' read -ra VERSION BUILD_META <<< "$VERSION" # Separate out the prerelease part, if any # (version.go expects it to be in a separate variable) - IFS='-' read -ra PRERELEASE_PARTS <<< "$VERSION" - BASE_VERSION="${PRERELEASE_PARTS[0]}" - PRERELEASE="${PRERELEASE_PARTS[1]}" + IFS='-' read -r BASE_VERSION PRERELEASE <<< "$VERSION" EXPERIMENTS_ENABLED=0 if [[ "$PRERELEASE" == alpha* ]]; then