Sync from Copyberry #289
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| on: | |
| push: | |
| branches: | |
| - master | |
| tags: | |
| - "v*" # release tags must be v<semver> | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| GO_VERSION: "1.26.x" | |
| GOPROXY: https://proxy.golang.org | |
| MODULE_PATH: github.com/openai/tunnel-client | |
| BINARY_NAME: tunnel-client | |
| PUBLIC_STORAGE_ACCOUNT: prod1pstatic | |
| PUBLIC_STORAGE_CONTAINER: persistent | |
| PUBLIC_BUCKET_PREFIX: tunnel-client | |
| PUBLIC_BASE_URL_ROOT: https://persistent.oaistatic.com | |
| AZURE_TENANT_ID: a48cca56-e6da-484e-a814-9c849652bcb3 | |
| AZURE_CLIENT_ID: 14c0c62b-2f5a-4a7f-aaca-bfbc980645fa | |
| AZURE_SUBSCRIPTION_ID: c24a3833-f66c-4c0b-8263-91c5cc408ff9 | |
| jobs: | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Validate release tag | |
| if: ${{ github.ref_type == 'tag' }} | |
| run: | | |
| ./scripts/release_tag.sh parse "${GITHUB_REF_NAME}" | |
| ./scripts/release_tag.sh check-source-version "${GITHUB_REF_NAME}" | |
| - name: Test release tag tooling | |
| run: bash ./scripts/release_tag_test.sh | |
| - name: Validate bundled cloudflared manifest | |
| run: | | |
| set -euo pipefail | |
| ./scripts/build_cloudflared.sh --describe --goos linux --goarch amd64 | |
| ./scripts/build_cloudflared.sh --describe --goos linux --goarch arm64 | |
| ./scripts/build_cloudflared.sh --describe --goos darwin --goarch amd64 | |
| ./scripts/build_cloudflared.sh --describe --goos darwin --goarch arm64 | |
| ./scripts/build_cloudflared.sh --describe --goos windows --goarch amd64 | |
| ./scripts/build_cloudflared.sh --describe --goos windows --goarch arm64 | |
| - name: Validate | |
| run: | | |
| go env | |
| go mod download | |
| go test ./... | |
| build: | |
| name: Build (${{ matrix.goos }}/${{ matrix.goarch }}) | |
| needs: test | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - goos: linux | |
| goarch: amd64 | |
| ext: "" | |
| - goos: linux | |
| goarch: arm64 | |
| ext: "" | |
| - goos: darwin | |
| goarch: amd64 | |
| ext: "" | |
| - goos: darwin | |
| goarch: arm64 | |
| ext: "" | |
| - goos: windows | |
| goarch: amd64 | |
| ext: ".exe" | |
| - goos: windows | |
| goarch: arm64 | |
| ext: ".exe" | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Build | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 0 | |
| TAG: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p dist/public dist/package-input | |
| BIN_NAME=${{ env.BINARY_NAME }}${{ matrix.ext }} | |
| LDFLAGS="-s -w -X ${{ env.MODULE_PATH }}/pkg/version.GitSHA=${GITHUB_SHA}" | |
| ASSET_TAG="${GITHUB_SHA::12}" | |
| if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then | |
| eval "$(./scripts/release_tag.sh parse "${TAG}")" | |
| LDFLAGS="${LDFLAGS} -X ${{ env.MODULE_PATH }}/pkg/version.semanticVersion=${release_version}" | |
| ASSET_TAG="${release_tag}" | |
| fi | |
| GOFLAGS="-trimpath -buildvcs=false" | |
| RAW_BINARY_NAME=${{ env.BINARY_NAME }}-${ASSET_TAG}-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }} | |
| CLOUDFLARED_RAW_NAME=cloudflared-${ASSET_TAG}-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }} | |
| go build $GOFLAGS -ldflags "$LDFLAGS" -o "dist/package-input/$RAW_BINARY_NAME" ./cmd/client | |
| ./scripts/build_cloudflared.sh \ | |
| --goos "${{ matrix.goos }}" \ | |
| --goarch "${{ matrix.goarch }}" \ | |
| --output "dist/package-input/$CLOUDFLARED_RAW_NAME" | |
| if [[ "${GITHUB_REF_TYPE}" == "tag" && "${{ matrix.goos }}" == "linux" && "${{ matrix.goarch }}" == "amd64" ]]; then | |
| expected_version="${release_version}+${GITHUB_SHA} (git sha: ${GITHUB_SHA})" | |
| actual_version="$("dist/package-input/$RAW_BINARY_NAME" --version)" | |
| if [[ "${actual_version}" != "${expected_version}" ]]; then | |
| echo "release binary version mismatch" >&2 | |
| printf 'expected: %s\n' "${expected_version}" >&2 | |
| printf 'actual: %s\n' "${actual_version}" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| if [[ "${{ matrix.goos }}" == "linux" && "${{ matrix.goarch }}" == "amd64" ]]; then | |
| expected_cloudflared_version="$(python3 -c 'import json; print(json.load(open("pkg/cloudflared/manifest.json"))["version"])')" | |
| actual_cloudflared_version="$("dist/package-input/$CLOUDFLARED_RAW_NAME" --version)" | |
| if [[ "${actual_cloudflared_version}" != *"${expected_cloudflared_version}"* ]]; then | |
| echo "bundled cloudflared version mismatch" >&2 | |
| printf 'expected substring: %s\n' "${expected_cloudflared_version}" >&2 | |
| printf 'actual: %s\n' "${actual_cloudflared_version}" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| if [[ "${{ matrix.goos }}" == "windows" && "${{ matrix.goarch }}" == "arm64" ]]; then | |
| expected_cloudflared_version="$(python3 -c 'import json; print(json.load(open("pkg/cloudflared/manifest.json"))["version"])')" | |
| if ! grep -a -Fq "${expected_cloudflared_version}" "dist/package-input/$CLOUDFLARED_RAW_NAME"; then | |
| echo "proxy-built cloudflared does not embed the pinned version" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| # Package as zip with OS/Arch/Tag in name | |
| ASSET_NAME=${{ env.BINARY_NAME }}-${ASSET_TAG}-${{ matrix.goos }}-${{ matrix.goarch }} | |
| stage_dir="$(mktemp -d)" | |
| cp "dist/package-input/$RAW_BINARY_NAME" "$stage_dir/$BIN_NAME" | |
| cp "dist/package-input/$CLOUDFLARED_RAW_NAME" "$stage_dir/cloudflared${{ matrix.ext }}" | |
| cp "pkg/cloudflared/manifest.json" "$stage_dir/cloudflared-manifest.json" | |
| cp "LICENSE" "$stage_dir/LICENSE" | |
| (cd "$stage_dir" && zip -9 "${GITHUB_WORKSPACE}/dist/public/$ASSET_NAME.zip" "$BIN_NAME" "cloudflared${{ matrix.ext }}" cloudflared-manifest.json LICENSE) | |
| rm -rf "$stage_dir" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: release-assets-${{ matrix.goos }}-${{ matrix.goarch }} | |
| path: dist/** | |
| if-no-files-found: error | |
| release: | |
| name: Release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| needs: build | |
| runs-on: macos-latest | |
| permissions: | |
| actions: read | |
| contents: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Derive release metadata | |
| id: release_meta | |
| run: | | |
| while IFS='=' read -r key value; do | |
| echo "${key}=${value}" >> "${GITHUB_OUTPUT}" | |
| done < <(./scripts/release_tag.sh parse "${GITHUB_REF_NAME}") | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| pattern: release-assets-* | |
| merge-multiple: true | |
| path: dist | |
| - name: Build combined distribution packages | |
| run: | | |
| ./scripts/build_distribution_package.sh \ | |
| --tag "${GITHUB_REF_NAME}" \ | |
| --binary-dir dist/package-input \ | |
| --output-dir dist/public | |
| - name: Generate SHA256 checksums | |
| working-directory: dist/public | |
| run: | | |
| shopt -s nullglob | |
| if command -v sha256sum >/dev/null 2>&1; then | |
| sha256sum *.zip *.tar.gz > SHA256SUMS.txt | |
| else | |
| shasum -a 256 *.zip *.tar.gz > SHA256SUMS.txt | |
| fi | |
| - name: Generate public URLs | |
| working-directory: dist/public | |
| env: | |
| PUBLIC_BASE_URL: ${{ steps.release_meta.outputs.public_base_url }} | |
| run: | | |
| { | |
| for file in *.zip *.tar.gz SHA256SUMS.txt; do | |
| printf '%s/%s\n' "${PUBLIC_BASE_URL}" "${file}" | |
| done | |
| } > PUBLIC_URLS.txt | |
| - name: Verify Azure CLI on macOS | |
| run: | | |
| set -euo pipefail | |
| command -v az | |
| az version | |
| - name: Azure login for public artifact upload | |
| uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0 | |
| with: | |
| tenant-id: ${{ env.AZURE_TENANT_ID }} | |
| client-id: ${{ env.AZURE_CLIENT_ID }} | |
| subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }} | |
| - name: Upload public artifacts | |
| run: | | |
| az storage blob upload-batch \ | |
| --subscription "${AZURE_SUBSCRIPTION_ID}" \ | |
| --account-name "${PUBLIC_STORAGE_ACCOUNT}" \ | |
| --destination "${PUBLIC_STORAGE_CONTAINER}" \ | |
| --destination-path "${{ steps.release_meta.outputs.public_blob_path }}" \ | |
| --source dist/public \ | |
| --auth-mode login \ | |
| --overwrite true | |
| - name: Verify public artifact URLs | |
| working-directory: dist/public | |
| run: | | |
| while IFS= read -r url; do | |
| for attempt in 1 2 3 4 5; do | |
| if curl -fsSI "${url}" >/dev/null; then | |
| break | |
| fi | |
| if [[ "${attempt}" -eq 5 ]]; then | |
| echo "failed to verify ${url}" >&2 | |
| exit 1 | |
| fi | |
| sleep 2 | |
| done | |
| done < PUBLIC_URLS.txt | |
| # Optional signing: | |
| # - name: Import GPG key | |
| # if: ${{ secrets.GPG_PRIVATE_KEY && secrets.GPG_PASSPHRASE }} | |
| # run: | | |
| # echo "$GPG_PRIVATE_KEY" | gpg --batch --yes --import | |
| # env: | |
| # GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| # - name: Sign checksums | |
| # if: ${{ secrets.GPG_PRIVATE_KEY && secrets.GPG_PASSPHRASE }} | |
| # working-directory: dist | |
| # env: | |
| # PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| # run: | | |
| # echo "$PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 \ | |
| # --armor --detach-sign --output SHA256SUMS.txt.asc SHA256SUMS.txt | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: ${{ github.ref_name }} | |
| draft: false | |
| prerelease: ${{ steps.release_meta.outputs.prerelease == 'true' }} | |
| generate_release_notes: true | |
| files: | | |
| dist/public/*.zip | |
| dist/public/*.tar.gz | |
| dist/public/SHA256SUMS.txt | |
| dist/public/PUBLIC_URLS.txt |