Skip to content

Commit 9b8da9b

Browse files
authored
chore: Adding tip build workflows (#5823)
* chore: Adding tip build workflows * docs: Documenting tip builds * docs: Cleaning up tip build docs * fix: Fixing script * fix: Addressing review feedback * fix: Cleaning up workflow scripts * docs: Clarifying codesign status
1 parent b1ca435 commit 9b8da9b

7 files changed

Lines changed: 362 additions & 4 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# Script to upload tip build assets to S3
6+
# Usage: upload-tip-build.sh <bin-directory>
7+
#
8+
# Environment variables:
9+
# BUCKET - S3 bucket name (required)
10+
# PREFIX - S3 key prefix, e.g. "tip" or "test" (required)
11+
# COMMIT_SHA - Git commit SHA used as the build ref (required)
12+
13+
function main {
14+
local -r bin_dir="${1:-bin}"
15+
16+
if [[ ! -d "$bin_dir" ]]; then
17+
echo "ERROR: Directory $bin_dir does not exist" >&2
18+
exit 1
19+
fi
20+
21+
if [[ -z "${BUCKET:-}" ]]; then
22+
echo "ERROR: BUCKET environment variable is not set" >&2
23+
exit 1
24+
fi
25+
26+
if [[ -z "${PREFIX:-}" ]]; then
27+
echo "ERROR: PREFIX environment variable is not set" >&2
28+
exit 1
29+
fi
30+
31+
if [[ -z "${COMMIT_SHA:-}" ]]; then
32+
echo "ERROR: COMMIT_SHA environment variable is not set" >&2
33+
exit 1
34+
fi
35+
36+
local -r s3_path="s3://${BUCKET}/${PREFIX}/${COMMIT_SHA}"
37+
echo "Uploading to ${s3_path}/"
38+
39+
local pids=()
40+
41+
# Upload tar.gz archives
42+
local filename
43+
for f in "${bin_dir}"/*.tar.gz; do
44+
filename="$(basename "$f")"
45+
echo "Uploading ${filename}..."
46+
aws s3 cp "${bin_dir}/${filename}" "${s3_path}/${filename}" &
47+
pids+=($!)
48+
done
49+
50+
# Upload checksums and signatures
51+
for f in SHA256SUMS SHA256SUMS.gpgsig SHA256SUMS.sigstore.json; do
52+
if [[ ! -f "${bin_dir}/${f}" ]]; then
53+
echo "WARNING: ${f} not found in ${bin_dir}, skipping" >&2
54+
continue
55+
fi
56+
echo "Uploading ${f}..."
57+
aws s3 cp "${bin_dir}/${f}" "${s3_path}/${f}" &
58+
pids+=($!)
59+
done
60+
61+
# Wait for all uploads and fail if any failed
62+
local failed=0
63+
for pid in "${pids[@]}"; do
64+
if ! wait "$pid"; then
65+
failed=1
66+
fi
67+
done
68+
69+
if [[ "$failed" -ne 0 ]]; then
70+
echo "ERROR: One or more uploads failed" >&2
71+
return 1
72+
fi
73+
74+
echo ""
75+
echo "Upload complete to ${s3_path}/"
76+
return 0
77+
}
78+
79+
main "$@"

.github/workflows/build.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ name: Build
22

33
on:
44
workflow_call:
5+
inputs:
6+
version:
7+
description: 'Version string for ldflags (defaults to github.ref_name)'
8+
required: false
9+
type: string
10+
default: ''
511

612
jobs:
713
detect_release:
@@ -87,13 +93,14 @@ jobs:
8793
GOOS: ${{ matrix.os }}
8894
GOARCH: ${{ matrix.arch }}
8995
CGO_ENABLED: 0
96+
BUILD_VERSION: ${{ inputs.version || github.ref_name }}
9097
run: |
9198
OUTPUT="bin/terragrunt_${GOOS}_${GOARCH}"
9299
if [[ "${GOOS}" == "windows" ]]; then
93100
OUTPUT="${OUTPUT}.exe"
94101
fi
95102
go build -o "${OUTPUT}" \
96-
-ldflags "-s -w -X github.com/gruntwork-io/go-commons/version.Version=${GITHUB_REF_NAME}" \
103+
-ldflags "-s -w -X github.com/gruntwork-io/go-commons/version.Version=${BUILD_VERSION}" \
97104
.
98105
99106
- name: Verify Static Linking

.github/workflows/ci.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,28 @@ jobs:
7070
build:
7171
needs: [lint, precommit, go_mod_tidy_check]
7272
uses: ./.github/workflows/build.yml
73+
with:
74+
version: ${{ github.ref == 'refs/heads/main' && format('tip-{0}', github.sha) || '' }}
7375
permissions:
7476
contents: read
7577
secrets: inherit
7678

79+
tip_build:
80+
needs: [build]
81+
if: github.ref == 'refs/heads/main'
82+
uses: ./.github/workflows/upload-tip-build.yml
83+
with:
84+
prefix: tip
85+
permissions:
86+
contents: read
87+
id-token: write
88+
actions: read
89+
secrets:
90+
TIP_BUILD_ROLE_ARN: ${{ secrets.TIP_BUILD_ROLE_ARN }}
91+
TIP_BUILD_BUCKET: ${{ secrets.TIP_BUILD_BUCKET }}
92+
SIGNING_GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }}
93+
SIGNING_GPG_PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }}
94+
7795
build_no_proxy:
7896
# Only run no_proxy builds on main branch to save CI time
7997
if: github.ref == 'refs/heads/main'

.github/workflows/test-build.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Test Build
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
build:
8+
name: Build Binaries
9+
uses: ./.github/workflows/build.yml
10+
with:
11+
version: ${{ github.ref == 'refs/heads/main' && 'tip' || 'test' }}-${{ github.sha }}
12+
permissions:
13+
contents: read
14+
15+
upload:
16+
needs: [build]
17+
uses: ./.github/workflows/upload-tip-build.yml
18+
with:
19+
prefix: ${{ github.ref == 'refs/heads/main' && 'tip' || 'test' }}
20+
permissions:
21+
contents: read
22+
id-token: write
23+
actions: read
24+
secrets:
25+
TIP_BUILD_ROLE_ARN: ${{ secrets.TIP_BUILD_ROLE_ARN }}
26+
TIP_BUILD_BUCKET: ${{ secrets.TIP_BUILD_BUCKET }}
27+
SIGNING_GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }}
28+
SIGNING_GPG_PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Upload Tip Build
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
prefix:
7+
description: 'S3 key prefix for uploaded assets (e.g. "tip" or "test")'
8+
required: true
9+
type: string
10+
secrets:
11+
TIP_BUILD_ROLE_ARN:
12+
required: false
13+
TIP_BUILD_BUCKET:
14+
required: false
15+
SIGNING_GPG_PRIVATE_KEY:
16+
required: false
17+
SIGNING_GPG_PASSPHRASE:
18+
required: false
19+
20+
jobs:
21+
upload:
22+
name: Package, Sign, and Upload to S3
23+
runs-on: ubuntu-latest
24+
permissions:
25+
contents: read
26+
id-token: write
27+
actions: read
28+
29+
steps:
30+
- name: Check if tip build secrets are set
31+
id: check_secrets
32+
env:
33+
ROLE_ARN: ${{ secrets.TIP_BUILD_ROLE_ARN }}
34+
BUCKET: ${{ secrets.TIP_BUILD_BUCKET }}
35+
run: |
36+
if [[ -n "${ROLE_ARN}" && -n "${BUCKET}" ]]; then
37+
echo "has_secrets=true" >> "$GITHUB_OUTPUT"
38+
echo "Tip build secrets are configured"
39+
else
40+
echo "has_secrets=false" >> "$GITHUB_OUTPUT"
41+
echo "Tip build secrets are NOT configured - skipping"
42+
fi
43+
44+
- name: Checkout code
45+
if: steps.check_secrets.outputs.has_secrets == 'true'
46+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
47+
48+
- name: Download all build artifacts
49+
if: steps.check_secrets.outputs.has_secrets == 'true'
50+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
51+
with:
52+
pattern: terragrunt_*
53+
path: bin/
54+
merge-multiple: true
55+
56+
- name: Verify binaries downloaded
57+
if: steps.check_secrets.outputs.has_secrets == 'true'
58+
run: .github/scripts/release/verify-binaries-downloaded.sh bin
59+
60+
- name: Set execution permissions
61+
if: steps.check_secrets.outputs.has_secrets == 'true'
62+
run: chmod +x bin/terragrunt_*
63+
64+
- name: Create tar.gz archives
65+
if: steps.check_secrets.outputs.has_secrets == 'true'
66+
run: |
67+
cd bin
68+
for binary in terragrunt_*; do
69+
tar -czf "${binary}.tar.gz" "$binary"
70+
echo "Created: ${binary}.tar.gz"
71+
done
72+
73+
- name: Remove bare binaries
74+
if: steps.check_secrets.outputs.has_secrets == 'true'
75+
run: |
76+
cd bin
77+
for f in terragrunt_*; do
78+
if [[ "$f" != *.tar.gz ]]; then
79+
rm "$f"
80+
fi
81+
done
82+
83+
- name: Generate SHA256SUMS
84+
if: steps.check_secrets.outputs.has_secrets == 'true'
85+
run: .github/scripts/release/generate-checksums.sh bin
86+
87+
- name: Import GPG key
88+
if: steps.check_secrets.outputs.has_secrets == 'true'
89+
env:
90+
SIGNING_GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }}
91+
run: |
92+
echo "${SIGNING_GPG_PRIVATE_KEY}" | base64 --decode | gpg --batch --import
93+
GPG_FINGERPRINT=$(gpg --list-secret-keys --keyid-format LONG | awk '/^sec/{sub(/.*\//, "", $2); print $2; exit}')
94+
echo "GPG_FINGERPRINT=${GPG_FINGERPRINT}" >> "${GITHUB_ENV}"
95+
96+
- name: Install Cosign
97+
if: steps.check_secrets.outputs.has_secrets == 'true'
98+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4
99+
100+
- name: Sign SHA256SUMS
101+
if: steps.check_secrets.outputs.has_secrets == 'true'
102+
env:
103+
SIGNING_GPG_PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }}
104+
run: .github/scripts/release/sign-checksums.sh bin
105+
106+
- name: Configure AWS credentials
107+
if: steps.check_secrets.outputs.has_secrets == 'true'
108+
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
109+
with:
110+
role-to-assume: ${{ secrets.TIP_BUILD_ROLE_ARN }}
111+
aws-region: us-east-1
112+
113+
- name: Upload to S3
114+
if: steps.check_secrets.outputs.has_secrets == 'true'
115+
env:
116+
BUCKET: ${{ secrets.TIP_BUILD_BUCKET }}
117+
PREFIX: ${{ inputs.prefix }}
118+
COMMIT_SHA: ${{ github.sha }}
119+
run: .github/scripts/upload-tip-build.sh bin

0 commit comments

Comments
 (0)