Merge pull request #5 from pulseengine/fix/update-deps-and-add-go-p3 #12
Workflow file for this run
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: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Tag to release (e.g., v1.0.0)" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| id-token: write | |
| attestations: write | |
| jobs: | |
| build-release: | |
| name: Build Release Components | |
| runs-on: ubuntu-latest | |
| outputs: | |
| tag_name: ${{ steps.get_tag.outputs.tag_name }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get tag name | |
| id: get_tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "tag_name=${{ inputs.tag }}" >> $GITHUB_OUTPUT | |
| else | |
| echo "tag_name=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Install Bazelisk | |
| run: | | |
| curl -LO https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-amd64 | |
| chmod +x bazelisk-linux-amd64 | |
| sudo mv bazelisk-linux-amd64 /usr/local/bin/bazel | |
| - name: Build all components | |
| run: bazel build //... | |
| - name: Collect release artifacts | |
| id: collect | |
| run: | | |
| TAG_NAME="${{ steps.get_tag.outputs.tag_name }}" | |
| VERSION=${TAG_NAME#v} | |
| RELEASE_DIR="release-${VERSION}" | |
| mkdir -p "${RELEASE_DIR}/c" "${RELEASE_DIR}/cpp" "${RELEASE_DIR}/rust" | |
| # Use bazel cquery to reliably find built WASM files | |
| echo "=== Collecting C components ===" | |
| for f in $(bazel cquery --output=files '//c:all' 2>/dev/null); do | |
| if [[ "$f" == *.wasm ]]; then | |
| echo "Found: $f" | |
| cp "$f" "${RELEASE_DIR}/c/" | |
| fi | |
| done | |
| echo "=== Collecting C++ components ===" | |
| for f in $(bazel cquery --output=files '//cpp:all' 2>/dev/null); do | |
| if [[ "$f" == *.wasm ]]; then | |
| echo "Found: $f" | |
| cp "$f" "${RELEASE_DIR}/cpp/" | |
| fi | |
| done | |
| echo "=== Collecting Rust CLI components ===" | |
| for target in hello_rust calculator datetime; do | |
| echo "Collecting ${target}..." | |
| # rust_wasm_binary creates runfiles with *_host.wasm | |
| wasm_file="bazel-bin/rust/${target}.runfiles/_main/rust/${target}_host.wasm" | |
| if [ -f "$wasm_file" ] || [ -L "$wasm_file" ]; then | |
| echo "Found: $wasm_file" | |
| cp -L "$wasm_file" "${RELEASE_DIR}/rust/${target}.wasm" | |
| else | |
| # Fallback: search in bazel-bin | |
| alt_wasm=$(find bazel-bin/rust -name "${target}*host.wasm" -type f 2>/dev/null | head -1) | |
| if [ -n "$alt_wasm" ]; then | |
| echo "Found (alt): $alt_wasm" | |
| cp -L "$alt_wasm" "${RELEASE_DIR}/rust/${target}.wasm" | |
| else | |
| echo "WARNING: Could not find ${target}.wasm" | |
| fi | |
| fi | |
| done | |
| echo "=== Collecting Rust YOLO components ===" | |
| for profile in debug release; do | |
| echo "Collecting yolo_inference_${profile}..." | |
| # Use bazel cquery to get the exact output path | |
| wasm_file=$(bazel cquery --output=files "//rust:yolo_inference_${profile}" 2>/dev/null | grep '\.wasm$' | head -1) | |
| if [ -n "$wasm_file" ] && [ -f "$wasm_file" ]; then | |
| echo "Found: $wasm_file" | |
| cp -L "$wasm_file" "${RELEASE_DIR}/rust/yolo_inference_${profile}.wasm" | |
| else | |
| echo "WARNING: Could not find yolo_inference_${profile}.wasm" | |
| fi | |
| done | |
| # List what we collected | |
| echo "=== Collected artifacts ===" | |
| find "${RELEASE_DIR}" -name "*.wasm" -type f | |
| # Verify we have files | |
| WASM_COUNT=$(find "${RELEASE_DIR}" -name "*.wasm" -type f | wc -l) | |
| echo "Total WASM files collected: $WASM_COUNT" | |
| # Debug: show all available WASM files | |
| echo "=== All available WASM files ===" | |
| echo "In bazel-bin (following symlinks):" | |
| find -L bazel-bin -name "*.wasm" -type f 2>/dev/null | head -20 || echo "None in bazel-bin" | |
| echo "In bazel-out:" | |
| find bazel-out -name "*.wasm" -type f 2>/dev/null | head -20 || echo "None in bazel-out" | |
| if [ "$WASM_COUNT" -eq 0 ]; then | |
| echo "ERROR: No WASM files were collected!" | |
| exit 1 | |
| fi | |
| if [ "$WASM_COUNT" -lt 4 ]; then | |
| echo "WARNING: Expected at least 4 WASM files, got $WASM_COUNT" | |
| fi | |
| # Create archive | |
| ARCHIVE_NAME="wasm-components-${VERSION}.tar.gz" | |
| tar -czvf "$ARCHIVE_NAME" "${RELEASE_DIR}" | |
| echo "archive_name=$ARCHIVE_NAME" >> $GITHUB_OUTPUT | |
| echo "release_dir=$RELEASE_DIR" >> $GITHUB_OUTPUT | |
| echo "" | |
| echo "Created release archive:" | |
| ls -la "$ARCHIVE_NAME" | |
| echo "" | |
| echo "Contents:" | |
| tar -tzvf "$ARCHIVE_NAME" | |
| - name: Build wsc for signing | |
| run: | | |
| echo "Building wsc (WebAssembly Signature Component)..." | |
| git clone --depth 1 https://github.com/pulseengine/wsc.git /tmp/wsc | |
| cd /tmp/wsc | |
| cargo build --release --bin wsc | |
| sudo cp target/release/wsc /usr/local/bin/wsc | |
| wsc --version || echo "wsc built successfully" | |
| - name: Sign release components (keyless) | |
| run: | | |
| RELEASE_DIR="${{ steps.collect.outputs.release_dir }}" | |
| echo "🔐 Signing WASM artifacts with wsc keyless signing..." | |
| echo " - Identity: GitHub Actions OIDC" | |
| echo " - Certificate: Short-lived from Fulcio (Sigstore)" | |
| echo " - Transparency: Logged in Rekor" | |
| echo "" | |
| # Sign all WASM files with keyless signing | |
| find "${RELEASE_DIR}" -name "*.wasm" | while read wasm_file; do | |
| echo "Signing: $wasm_file" | |
| signed_file="${wasm_file%.wasm}.signed.wasm" | |
| wsc sign --keyless \ | |
| --input-file "$wasm_file" \ | |
| --output-file "$signed_file" | |
| # Replace original with signed version | |
| mv "$signed_file" "$wasm_file" | |
| done | |
| echo "✅ All WASM files signed with wsc (keyless)" | |
| # Create signed archive | |
| SIGNED_ARCHIVE="wasm-components-${{ steps.get_tag.outputs.tag_name }}-signed.tar.gz" | |
| tar -czvf "$SIGNED_ARCHIVE" "${RELEASE_DIR}" | |
| echo "signed_archive=$SIGNED_ARCHIVE" >> $GITHUB_OUTPUT | |
| - name: Generate Release Notes | |
| run: | | |
| TAG_NAME="${{ steps.get_tag.outputs.tag_name }}" | |
| cat > RELEASE_NOTES.md << 'EOF' | |
| ## WebAssembly Component Examples ${{ steps.get_tag.outputs.tag_name }} | |
| This release contains WebAssembly components built with [rules_wasm_component](https://github.com/pulseengine/rules_wasm_component). | |
| ### Components Included | |
| **C Components:** | |
| - `hello_c_cli.wasm` - CLI executable (runs with wasmtime) | |
| - `hello_c_debug.wasm` - Library component (debug) | |
| - `hello_c_release.wasm` - Library component (release) | |
| **C++ Components:** | |
| - `hello_cpp_cli.wasm` - CLI executable (runs with wasmtime) | |
| - `hello_cpp_debug.wasm` - Library component (debug) | |
| - `hello_cpp_release.wasm` - Library component (release) | |
| **Rust Components:** | |
| - `hello_rust.wasm` - Hello World CLI | |
| - `calculator.wasm` - Arithmetic calculator | |
| - `datetime.wasm` - Date/time display | |
| - `yolo_inference_debug.wasm` - YOLO detection (debug) | |
| - `yolo_inference_release.wasm` - YOLO detection (release) | |
| ### Security | |
| All components are signed using [wsc](https://github.com/pulseengine/wsc) with keyless Sigstore signing: | |
| - **Identity**: GitHub Actions OIDC | |
| - **Certificate**: Short-lived from Fulcio | |
| - **Transparency**: Logged in Rekor | |
| ### Running Components | |
| ```bash | |
| # Install wasmtime | |
| curl https://wasmtime.dev/install.sh -sSf | bash | |
| # Run C/C++ CLI examples | |
| wasmtime run hello_c_cli.wasm | |
| wasmtime run hello_cpp_cli.wasm | |
| # Run Rust CLI examples | |
| wasmtime run hello_rust.wasm | |
| wasmtime run calculator.wasm 8 + 8 | |
| wasmtime run datetime.wasm | |
| # Run YOLO detection (requires ONNX model) | |
| wasmtime run --dir . -S cli -S nn -S nn-graph=onnx::./models/yolov8n \ | |
| yolo_inference_release.wasm ./image.jpg | |
| ``` | |
| ### Verification | |
| Signatures can be verified using wsc: | |
| ```bash | |
| wsc verify --keyless \ | |
| --identity "https://github.com/${{ github.repository }}" \ | |
| --issuer "https://token.actions.githubusercontent.com" \ | |
| --input-file component.wasm | |
| ``` | |
| EOF | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.get_tag.outputs.tag_name }} | |
| name: Release ${{ steps.get_tag.outputs.tag_name }} | |
| body_path: RELEASE_NOTES.md | |
| files: | | |
| ${{ steps.collect.outputs.archive_name }} | |
| wasm-components-${{ steps.get_tag.outputs.tag_name }}-signed.tar.gz | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: true | |
| make_latest: true | |
| - name: Generate Provenance Attestation | |
| uses: actions/attest-build-provenance@v2 | |
| with: | |
| subject-path: ${{ steps.collect.outputs.archive_name }} |