Back to Formatjs

FormatJS Rust CLI - Release Guide

crates/formatjs_cli/RELEASE.md

4.5.07.7 KB
Original Source

FormatJS Rust CLI - Release Guide

This document explains how to build release binaries for the FormatJS Rust CLI for multiple platforms.

Quick Start

The repository includes two GitHub Actions workflows:

1. Build & Test Workflow (.github/workflows/rust-cli-test.yml)

Runs automatically on:

  • Pull requests that modify Rust code
  • Pushes to main branch
  • Can be triggered manually

What it does:

  • Builds Rust CLI on both macOS and Linux
  • Runs unit tests
  • Runs integration tests
  • Performs smoke tests

2. Release Workflow (.github/workflows/rust-cli-release.yml)

Triggered by: Push a tag starting with formatjs_cli_v (e.g., formatjs_cli_v0.1.0)

bash
# Create and push a release tag
git tag formatjs_cli_v0.1.0
git push origin formatjs_cli_v0.1.0

What it does:

  1. Build macOS ARM64 binary natively on macOS runner
  2. Build Linux x86_64 binary natively on Linux runner
  3. Run smoke tests on both binaries
  4. Combine artifacts and generate checksums
  5. Create a GitHub Release with all binaries

Release artifacts:

  • formatjs_cli-darwin-arm64 (macOS Apple Silicon)
  • formatjs_cli-linux-x64 (Linux x86_64)
  • checksums.txt (SHA-256 checksums)

Option 2: Using Cargo

bash
cd crates/formatjs_cli
./release.sh

This uses native Cargo cross-compilation. Requires additional setup for cross-compilation (see below).

Platform Support

PlatformArchitectureTarget TripleStatus
macOSApple Siliconaarch64-apple-darwin✅ Native (Bazel on GHA macOS runner)
Linuxx86_64x86_64-unknown-linux-gnu✅ Native (Bazel on GHA Linux runner)

Note: The GitHub Actions workflow builds each platform natively on its respective runner, avoiding complex cross-compilation setup.

Cross-Compilation Setup

For Linux builds from macOS

You have several options:

Option A: Using Zig (Easiest)

bash
# Install zig (provides a cross-platform linker)
brew install zig

# Add Linux target
rustup target add x86_64-unknown-linux-gnu

# Zig will be automatically detected and used as the linker

Option B: Using musl (Static binaries)

bash
# Add musl target (produces static binaries)
rustup target add x86_64-unknown-linux-musl

# Build
cargo build --release --target x86_64-unknown-linux-musl

Option C: Using cross

bash
# Install cross (Docker-based cross-compilation)
cargo install cross

# Build
cross build --release --target x86_64-unknown-linux-gnu

Manual Building

Build with Bazel

bash
# Build for current platform
bazel build --compilation_mode=opt //crates/formatjs_cli:release_binary

# Build for specific platform (requires being on that platform)
# macOS ARM64:
bazel build --compilation_mode=opt --platforms=//crates/formatjs_cli/platforms:darwin_arm64 //crates/formatjs_cli:release_binary

# Linux x86_64:
bazel build --compilation_mode=opt --platforms=//crates/formatjs_cli/platforms:linux_x86_64 //crates/formatjs_cli:release_binary

Binary will be in bazel-bin/crates/formatjs_cli/formatjs_cli_release.

Note: Bazel builds each platform natively (no cross-compilation). Use GitHub Actions to build both platforms.

Build for specific platform with Cargo

bash
# macOS Apple Silicon
cargo build --release --target aarch64-apple-darwin

# macOS Intel
cargo build --release --target x86_64-apple-darwin

# Linux x86_64 (requires cross-compilation setup)
cargo build --release --target x86_64-unknown-linux-gnu

Binaries will be in target/<triple>/release/formatjs_cli.

Release Artifacts

After running the GitHub Actions workflow, artifacts will be available:

  1. During the workflow run: As job artifacts (7 day retention)
  2. After tag push: As GitHub Release assets
Release assets:
├── formatjs_cli-darwin-arm64      # macOS Apple Silicon
├── formatjs_cli-linux-x64         # Linux x86_64
└── checksums.txt                  # SHA-256 checksums

Verify checksums

bash
# Download from release
curl -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v0.1.0/checksums.txt
curl -LO https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v0.1.0/formatjs_cli-darwin-arm64

shasum -a 256 -c checksums.txt

Testing Binaries

The GitHub Actions workflow includes smoke tests that run automatically:

bash
./formatjs_cli-{platform} --version
./formatjs_cli-{platform} --help

To test manually after downloading:

bash
# macOS Apple Silicon
chmod +x formatjs_cli-darwin-arm64
./formatjs_cli-darwin-arm64 --version

# Linux
chmod +x formatjs_cli-linux-x64
./formatjs_cli-linux-x64 --version

Publishing

The GitHub Actions workflow automates the entire release process:

  1. Tag the release:

    bash
    # Update version in Cargo.toml if needed
    git tag formatjs_cli_v0.1.0
    git push origin formatjs_cli_v0.1.0
    
  2. Workflow runs automatically:

    • Builds both macOS and Linux binaries
    • Runs smoke tests
    • Creates GitHub Release with all artifacts
  3. Manual verification (optional):

    • Check GitHub Actions run completed successfully
    • Download and test binaries from the release
    • Verify checksums
  4. Publish to npm (if applicable):

    bash
    # Update package.json with release URLs
    # Point to GitHub release assets
    npm publish
    

Troubleshooting

Linux cross-compilation fails

Problem: cargo build --target x86_64-unknown-linux-gnu fails with linker errors.

Solutions:

  1. Install zig: brew install zig (easiest)
  2. Use musl target: cargo build --target x86_64-unknown-linux-musl
  3. Use cross: cargo install cross && cross build --target x86_64-unknown-linux-gnu
  4. Build on an actual Linux machine

Binary doesn't run on target platform

Problem: Binary fails to execute with "exec format error" or "cannot execute binary file".

Cause: Binary was built for wrong architecture.

Solution: Verify the target triple matches your platform:

bash
file dist/v<version>/formatjs_cli-*

"Unknown platform" error with Bazel

Problem: Bazel can't find the platform definition.

Solution: Ensure rules_rust is properly configured in MODULE.bazel or WORKSPACE.

CI/CD Integration

The repository includes two production-ready GitHub Actions workflows:

1. Build & Test Workflow (.github/workflows/rust-cli-test.yml)

Purpose: Continuous integration for all changes

Triggers:

  • Pull requests modifying Rust code
  • Pushes to main branch
  • Manual dispatch

Jobs:

yaml
build-and-test-macos: # Build and test on macOS runner
build-and-test-linux: # Build and test on Linux runner

Features:

  • Concurrent testing on both platforms
  • Unit tests and integration tests
  • Smoke tests for binaries
  • BuildBuddy integration (optional, via API key)

2. Release Workflow (.github/workflows/rust-cli-release.yml)

Purpose: Create official releases with binaries

Triggers:

  • Push a tag starting with formatjs_cli_v

Jobs:

yaml
build-macos: # Build macOS binary
build-linux: # Build Linux binary
combine-and-release: # Combine, checksum, and create release

Features:

  1. Multi-platform builds: macOS and Linux built natively
  2. Smoke tests: Automatic testing with --version and --help
  3. Artifact management: 7-day retention during workflow, permanent in releases
  4. Checksum generation: Automatic SHA-256 checksums
  5. GitHub Release: Automatic creation with formatted release notes
  6. BuildBuddy integration: Optional remote caching

License

Same as the main FormatJS project (MIT).