Skip to content

Build Artifacts satyakigh push (66444a221557d4b9b144a762bd141d942d4163e8) #184

Build Artifacts satyakigh push (66444a221557d4b9b144a762bd141d942d4163e8)

Build Artifacts satyakigh push (66444a221557d4b9b144a762bd141d942d4163e8) #184

name: Build Artifacts
run-name: Build Artifacts ${{ github.actor }} ${{ github.event_name }} (${{ inputs.branch || github.sha }})
on:
push:
branches: [ main ]
workflow_dispatch:
inputs:
branch:
description: "Branch to build artifacts from - main for regular builds, a hotfix branch for patch releases. The artifacts PR targets this branch."
required: false
type: string
default: 'main'
concurrency:
group: build-artifacts-${{ inputs.branch || 'main' }}
cancel-in-progress: true
permissions:
contents: read
jobs:
relevant-changes:
uses: ./.github/workflows/relevant-source-changes.yml
permissions:
contents: read
pull-requests: read
build-required:
needs: [ relevant-changes ]
if: ${{ needs.relevant-changes.outputs.relevant == 'true' }}
runs-on: ubuntu-latest
steps:
- run: echo "Artifact build required"
get-configs:
needs: [ build-required ]
uses: ./.github/workflows/configs.yml
resolve-ref:
needs: [ build-required ]
runs-on: ubuntu-latest
outputs:
sha: ${{ steps.head.outputs.sha }}
branch: ${{ steps.head.outputs.branch }}
pr-branch: ${{ steps.head.outputs.pr-branch }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.branch || github.sha }}
- name: Pin the build commit and PR target
id: head
env:
BRANCH: ${{ inputs.branch || 'main' }}
INPUT_BRANCH: ${{ inputs.branch }}
run: |
set -euo pipefail
PR_BRANCH="automated/build-artifacts"
if [ -n "$INPUT_BRANCH" ]; then
PR_BRANCH="$PR_BRANCH-${INPUT_BRANCH//\//-}"
fi
{
echo "sha=$(git rev-parse HEAD)"
echo "branch=$BRANCH"
echo "pr-branch=$PR_BRANCH"
} >> "$GITHUB_OUTPUT"
echo "Building from branch $BRANCH, commit $(git rev-parse HEAD); PR branch $PR_BRANCH"
generate-licenses:
needs: [ get-configs, resolve-ref ]
runs-on: ubuntu-latest
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Install Rust ${{ needs.get-configs.outputs.rust-toolchain }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: ${{ needs.get-configs.outputs.rust-toolchain }}
- name: Install cargo-about ${{ needs.get-configs.outputs.cargo-about-version }}
uses: taiki-e/install-action@v2.86.7
with:
tool: cargo-about@${{ needs.get-configs.outputs.cargo-about-version }}
- name: Log tool versions
uses: ./.github/actions/print-build-versions
- name: Generate THIRD-PARTY-LICENSES
run: python3 scripts/generate_licenses.py
- name: Upload license files
uses: actions/upload-artifact@v7
with:
name: third-party-licenses
path: |
${{ env.WORKING_DIR }}/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-jvm/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-wasm/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-python/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-go/go/THIRD-PARTY-LICENSES.txt
if-no-files-found: error
retention-days: 1
build-jvm:
needs: [ get-configs, resolve-ref, generate-licenses ]
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, platform: linux, arch: x64 }
- { os: ubuntu-24.04-arm, platform: linux, arch: aarch64 }
- { os: macos-latest, platform: darwin, arch: aarch64 }
- { os: macos-15-intel, platform: darwin, arch: x64 }
- { os: windows-latest, platform: win32, arch: x64 }
- { os: windows-11-arm, platform: win32, arch: aarch64, java-distribution: microsoft }
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Install Rust ${{ needs.get-configs.outputs.rust-toolchain }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: ${{ needs.get-configs.outputs.rust-toolchain }}
- name: Setup JVM toolchain
uses: ./.github/actions/setup-jvm-toolchain
with:
java-version: ${{ needs.get-configs.outputs.java-version }}
java-distribution: ${{ matrix.java-distribution || needs.get-configs.outputs.java-distribution }}
kotlin-version: ${{ needs.get-configs.outputs.kotlin-version }}
ktlint-version: ${{ needs.get-configs.outputs.ktlint-version }}
gradle-version: ${{ needs.get-configs.outputs.gradle-version }}
- name: Log tool versions
uses: ./.github/actions/print-build-versions
- name: Download THIRD-PARTY-LICENSES.txt
uses: actions/download-artifact@v8
with:
name: third-party-licenses
path: ${{ env.WORKING_DIR }}
- name: Build JVM bindings
working-directory: ${{ env.WORKING_DIR }}/bindings-jvm
run: ./build.sh
- name: Inject THIRD-PARTY-LICENSES.txt into JVM jar
working-directory: ${{ env.WORKING_DIR }}/bindings-jvm
run: |
set -euo pipefail
JAR_ABS="$(pwd)/generated/cloudformation-validate.jar"
LIC_ABS="$(pwd)/THIRD-PARTY-LICENSES.txt"
tmpdir="$(mktemp -d)"
mkdir -p "$tmpdir/META-INF"
cp "$LIC_ABS" "$tmpdir/META-INF/THIRD-PARTY-LICENSES.txt"
( cd "$tmpdir" && jar uf "$JAR_ABS" META-INF/THIRD-PARTY-LICENSES.txt )
rm -rf "$tmpdir"
unzip -l "$JAR_ABS" | grep -E 'META-INF/(LICENSE|THIRD-PARTY-LICENSES.txt)$'
- name: Upload JVM jar
uses: actions/upload-artifact@v7
with:
name: jvm-${{ matrix.platform }}-${{ matrix.arch }}
path: ${{ env.WORKING_DIR }}/bindings-jvm/generated/cloudformation-validate.jar
if-no-files-found: error
retention-days: 1
build-wasm:
needs: [ get-configs, resolve-ref, generate-licenses ]
runs-on: ubuntu-latest
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Install Rust ${{ needs.get-configs.outputs.rust-toolchain }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: ${{ needs.get-configs.outputs.rust-toolchain }}
- name: Setup Node.js ${{ needs.get-configs.outputs.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ needs.get-configs.outputs.node-version }}
- name: Install wasm-pack ${{ needs.get-configs.outputs.wasm-pack-version }}
uses: taiki-e/install-action@v2.86.7
with:
tool: wasm-pack@${{ needs.get-configs.outputs.wasm-pack-version }}
- name: Log tool versions
uses: ./.github/actions/print-build-versions
- name: Download THIRD-PARTY-LICENSES.txt
uses: actions/download-artifact@v8
with:
name: third-party-licenses
path: ${{ env.WORKING_DIR }}
- name: Build WASM bindings
working-directory: ${{ env.WORKING_DIR }}/bindings-wasm
run: ./build.sh
- name: Inject THIRD-PARTY-LICENSES.txt into WASM dist
working-directory: ${{ env.WORKING_DIR }}/bindings-wasm
run: |
set -euo pipefail
cp THIRD-PARTY-LICENSES.txt dist/THIRD-PARTY-LICENSES.txt
ls -la dist/
- name: Upload WASM dist
uses: actions/upload-artifact@v7
with:
name: wasm-dist
path: ${{ env.WORKING_DIR }}/bindings-wasm/dist
if-no-files-found: error
retention-days: 1
build-cli:
needs: [ get-configs, resolve-ref, generate-licenses ]
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, platform: linux, arch: x64 }
- { os: ubuntu-24.04-arm, platform: linux, arch: aarch64 }
- { os: macos-latest, platform: darwin, arch: aarch64 }
- { os: macos-15-intel, platform: darwin, arch: x64 }
- { os: windows-latest, platform: win32, arch: x64 }
- { os: windows-11-arm, platform: win32, arch: aarch64 }
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Install Rust ${{ needs.get-configs.outputs.rust-toolchain }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: ${{ needs.get-configs.outputs.rust-toolchain }}
- name: Log tool versions
uses: ./.github/actions/print-build-versions
- name: Build cfn-validate
working-directory: ${{ env.WORKING_DIR }}/cfn-validate
run: ./build.sh
- name: Upload cfn-validate binary
uses: actions/upload-artifact@v7
with:
name: cfn-validate-${{ matrix.platform }}-${{ matrix.arch }}
path: release-bin/cfn-validate-${{ matrix.platform }}-${{ matrix.arch }}*
if-no-files-found: error
retention-days: 1
build-python:
needs: [ get-configs, resolve-ref, generate-licenses ]
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, platform: linux, arch: x64 }
- { os: ubuntu-24.04-arm, platform: linux, arch: aarch64 }
- { os: macos-latest, platform: darwin, arch: aarch64 }
- { os: macos-15-intel, platform: darwin, arch: x64 }
- { os: windows-latest, platform: win32, arch: x64 }
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Install Rust ${{ needs.get-configs.outputs.rust-toolchain }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: ${{ needs.get-configs.outputs.rust-toolchain }}
- name: Setup Python ${{ needs.get-configs.outputs.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ needs.get-configs.outputs.python-version }}
- name: Log tool versions
uses: ./.github/actions/print-build-versions
- name: Download THIRD-PARTY-LICENSES.txt
uses: actions/download-artifact@v8
with:
name: third-party-licenses
path: ${{ env.WORKING_DIR }}
- name: Build Python bindings
working-directory: ${{ env.WORKING_DIR }}/bindings-python
run: ./build.sh
- name: Upload host Python wheel
uses: actions/upload-artifact@v7
with:
name: python-${{ matrix.platform }}-${{ matrix.arch }}
path: ${{ env.WORKING_DIR }}/bindings-python/generated/dist/*.whl
if-no-files-found: error
retention-days: 1
build-go:
needs: [ get-configs, resolve-ref, generate-licenses ]
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, platform: linux, arch: x64 }
- { os: macos-latest, platform: darwin, arch: aarch64 }
- { os: windows-latest, platform: win32, arch: x64, target: x86_64-pc-windows-gnu }
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Install Rust ${{ needs.get-configs.outputs.rust-toolchain }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: ${{ needs.get-configs.outputs.rust-toolchain }}${{ matrix.target && format('-{0}', matrix.target) || '' }}
targets: ${{ matrix.target || '' }}
- name: Setup Go ${{ needs.get-configs.outputs.go-version }}
uses: actions/setup-go@v6
with:
go-version: ${{ needs.get-configs.outputs.go-version }}
- name: Install uniffi-bindgen-go ${{ needs.get-configs.outputs.uniffi-bindgen-go-tag }}
run: cargo install uniffi-bindgen-go --git https://github.com/NordSecurity/uniffi-bindgen-go --tag '${{ needs.get-configs.outputs.uniffi-bindgen-go-tag }}'
- name: Log tool versions
uses: ./.github/actions/print-build-versions
- name: Download THIRD-PARTY-LICENSES.txt
uses: actions/download-artifact@v8
with:
name: third-party-licenses
path: ${{ env.WORKING_DIR }}
- name: Build Go bindings
working-directory: ${{ env.WORKING_DIR }}/bindings-go
run: ./build.sh
- name: Upload host Go module
uses: actions/upload-artifact@v7
with:
name: go-${{ matrix.platform }}-${{ matrix.arch }}
path: ${{ env.WORKING_DIR }}/bindings-go/go
if-no-files-found: error
retention-days: 1
pull-request:
needs: [ get-configs, resolve-ref, generate-licenses, build-jvm, build-wasm, build-cli, build-python, build-go ]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
env:
WORKING_DIR: ${{ needs.get-configs.outputs.working-dir }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.resolve-ref.outputs.sha }}
- name: Download all artifacts
uses: actions/download-artifact@v8
with:
path: incoming
- name: Stage artifacts
working-directory: ${{ env.WORKING_DIR }}
run: |
set -euo pipefail
rm -rf bindings-jvm/generated bindings-wasm/dist bindings-python/generated bindings-go/go/internal bindings-go/go/libs "$GITHUB_WORKSPACE/release-bin"
mkdir -p bindings-jvm/generated bindings-wasm/dist bindings-python/generated/dist bindings-go/go "$GITHUB_WORKSPACE/release-bin"
shopt -s nullglob
jars=("$GITHUB_WORKSPACE"/incoming/jvm-*/cloudformation-validate.jar)
if [ ${#jars[@]} -ne 6 ]; then
echo "::error::Expected six JVM jars under incoming/jvm-*/, found ${#jars[@]}"
exit 1
fi
base=""
for jar in "${jars[@]}"; do
case "$jar" in *jvm-linux-x64*) base="$jar" ;; esac
done
if [ -z "$base" ]; then
echo "::error::No Linux JVM jar (jvm-linux-x64) found under incoming/jvm-*/; refusing to fall back to a non-Linux base"
exit 1
fi
rest=()
for jar in "${jars[@]}"; do
[ "$jar" = "$base" ] || rest+=("$jar")
done
bindings-jvm/merge-jars.sh \
bindings-jvm/generated/cloudformation-validate.jar \
"$base" "${rest[@]}"
cp -R "$GITHUB_WORKSPACE/incoming/wasm-dist/." bindings-wasm/dist/
echo "Staged WASM dist:"; ls -1 bindings-wasm/dist
python_artifacts=(
python-linux-x64
python-linux-aarch64
python-darwin-x64
python-darwin-aarch64
python-win32-x64
)
for artifact in "${python_artifacts[@]}"; do
host_wheels=("$GITHUB_WORKSPACE/incoming/$artifact"/*.whl)
if [ ${#host_wheels[@]} -ne 1 ]; then
echo "::error::Expected exactly one Python wheel in incoming/$artifact, found ${#host_wheels[@]}"
exit 1
fi
wheel_name="$(basename "${host_wheels[0]}")"
if [ -e "bindings-python/generated/dist/$wheel_name" ]; then
echo "::error::Duplicate Python wheel filename: $wheel_name"
exit 1
fi
cp "${host_wheels[0]}" bindings-python/generated/dist/
done
staged_wheels=(bindings-python/generated/dist/*.whl)
if [ ${#staged_wheels[@]} -ne 5 ]; then
echo "::error::Expected five staged Python wheels, found ${#staged_wheels[@]}"
exit 1
fi
echo "Staged platform-specific Python wheels:"; printf ' %s\n' "${staged_wheels[@]}"
bindings-go/merge-modules.sh \
bindings-go/go \
"$GITHUB_WORKSPACE/incoming/go-linux-x64" \
"$GITHUB_WORKSPACE/incoming/go-darwin-aarch64" \
"$GITHUB_WORKSPACE/incoming/go-win32-x64"
echo "Merged all-platform Go module:"
find bindings-go/go/libs -mindepth 2 -maxdepth 2 -type f -name 'libbindings_go.a' -print | sort
for d in "$GITHUB_WORKSPACE"/incoming/cfn-validate-*/; do
cp -R "$d." "$GITHUB_WORKSPACE/release-bin/"
done
echo "Staged cfn-validate binaries:"; ls -1 "$GITHUB_WORKSPACE/release-bin" || true
cp "$GITHUB_WORKSPACE/incoming/third-party-licenses/THIRD-PARTY-LICENSES.txt" THIRD-PARTY-LICENSES.txt
cp "$GITHUB_WORKSPACE/incoming/third-party-licenses/bindings-jvm/THIRD-PARTY-LICENSES.txt" bindings-jvm/THIRD-PARTY-LICENSES.txt
cp "$GITHUB_WORKSPACE/incoming/third-party-licenses/bindings-wasm/THIRD-PARTY-LICENSES.txt" bindings-wasm/THIRD-PARTY-LICENSES.txt
cp "$GITHUB_WORKSPACE/incoming/third-party-licenses/bindings-python/THIRD-PARTY-LICENSES.txt" bindings-python/THIRD-PARTY-LICENSES.txt
cp "$GITHUB_WORKSPACE/incoming/third-party-licenses/bindings-go/go/THIRD-PARTY-LICENSES.txt" bindings-go/go/THIRD-PARTY-LICENSES.txt
echo "Staged THIRD-PARTY-LICENSES.txt files."
bindings-jvm/generate-version-properties.sh
echo "Merged JVM jar:"; ls -1 bindings-jvm/generated
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8.1.1
with:
commit-message: 'chore: Update bindings'
branch: ${{ needs.resolve-ref.outputs.pr-branch }}
delete-branch: true
title: 'chore: Update Bindings (from ${{ needs.resolve-ref.outputs.branch }})'
base: ${{ needs.resolve-ref.outputs.branch }}
body: |
Automated update of the binding bundles and CLI binaries.
* **JVM** - a single multi-platform `cloudformation-validate.jar` in
`${{ env.WORKING_DIR }}/bindings-jvm/generated/`, carrying the shared
Kotlin classes/sources plus every supported native library. Each target
is built by `bindings-jvm/build.sh` and the per-target natives are
combined via `bindings-jvm/merge-jars.sh`.
* **WASM** - `${{ env.WORKING_DIR }}/bindings-wasm/dist/`, built once via
`bindings-wasm/build.sh`; the `wasm32-unknown-unknown` package is portable
across supported Node.js hosts.
* **Python** - platform-specific wheels in
`${{ env.WORKING_DIR }}/bindings-python/generated/dist/`, one per
supported native target. Every wheel carries only its matching native
library plus README and license metadata, and has a real platform tag so
installers select exactly the compatible artifact.
* **Go** - a standalone all-platform module in
`${{ env.WORKING_DIR }}/bindings-go/go/`, carrying generated FFI source,
every platform's static library, README, LICENSE, and
THIRD-PARTY-LICENSES.txt. Each platform is built by
`bindings-go/build.sh`, then combined by `bindings-go/merge-modules.sh`.
* **cfn-validate CLI** - per-platform binaries in
`release-bin/`, built via `cfn-validate/build.sh`.
* **Third-party licenses** - `THIRD-PARTY-LICENSES.txt` files
regenerated by the workflow via `scripts/generate_licenses.py`.
labels: automated, build-artifacts
add-paths: |
${{ env.WORKING_DIR }}/bindings-jvm/generated/**
${{ env.WORKING_DIR }}/bindings-jvm/version.properties
${{ env.WORKING_DIR }}/bindings-jvm/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-wasm/dist/**
${{ env.WORKING_DIR }}/bindings-wasm/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-python/generated/dist/**
${{ env.WORKING_DIR }}/bindings-python/THIRD-PARTY-LICENSES.txt
${{ env.WORKING_DIR }}/bindings-go/go/internal/**
${{ env.WORKING_DIR }}/bindings-go/go/libs/**
${{ env.WORKING_DIR }}/bindings-go/go/README.md
${{ env.WORKING_DIR }}/bindings-go/go/LICENSE
${{ env.WORKING_DIR }}/bindings-go/go/THIRD-PARTY-LICENSES.txt
release-bin/**
${{ env.WORKING_DIR }}/THIRD-PARTY-LICENSES.txt