Skip to content

SMOL 1. BoringSSL

SMOL 1. BoringSSL #13

Workflow file for this run

name: SMOL 1. BoringSSL
on:
workflow_dispatch:
inputs:
dry-run:
description: 'Dry run (build only, no release)'
type: boolean
default: true
force:
description: 'Force rebuild (ignore cache)'
type: boolean
default: false
build-mode:
description: 'Build mode'
type: choice
options:
- prod
- dev
default: prod
debug:
description: 'Debug (0|1|namespace[,...])'
type: string
default: '0'
workflow_call:
inputs:
dry-run:
type: boolean
default: true
force:
type: boolean
default: false
build-mode:
type: string
default: prod
debug:
type: string
default: '0'
permissions:
contents: read
env:
HOMEBREW_NO_ANALYTICS: '1'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
build-boringssl:
permissions:
contents: read
id-token: write # OIDC authentication for Depot builds
name: boringssl / ${{ matrix.platform }}-${{ matrix.arch }}${{ matrix.libc == 'musl' && '-musl' || '' }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
# macOS builds. Depot runner depot-macos-15 = 8 vCPU M2, 24GB RAM.
# darwin-x64 still uses depot-macos-15 (ARM64 host); the build
# runs natively under cmake's ARCH-aware codegen path that
# every other builder workflow uses for both arches.
- runner: depot-macos-15
platform: darwin
arch: arm64
os: macos
- runner: depot-macos-15
platform: darwin
arch: x64
os: macos
# Linux builds (glibc)
- runner: ubuntu-24.04
platform: linux
arch: x64
os: linux
libc: glibc
- runner: ubuntu-24.04-arm
platform: linux
arch: arm64
os: linux
libc: glibc
# Linux builds (musl)
- runner: ubuntu-24.04
platform: linux
arch: x64
os: linux
libc: musl
- runner: ubuntu-24.04-arm
platform: linux
arch: arm64
os: linux
libc: musl
# Windows builds
- runner: windows-2022
platform: win32
arch: x64
os: windows
- runner: windows-2022
platform: win32
arch: arm64
os: windows
cross_compile: true
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 (2026-05-15)
with:
persist-credentials: false
# Only the boringssl submodule is initialized below.
submodules: false
- name: Enable debug logging
uses: ./.github/actions/enable-debug-logging
with:
debug: ${{ inputs.debug }}
- uses: SocketDev/socket-registry/.github/actions/setup@c291a14196d088970c0453e905b40969b11bf193 # main (2026-05-15)
- uses: SocketDev/socket-registry/.github/actions/install@75964f14e0682ae4aa846119e2fc9a710d970056 # main (2026-05-15)
- name: Load cache version from centralized config
id: cache-version
uses: ./.github/actions/load-cache-version
with:
package-name: boringssl
- name: Generate BoringSSL cache key
id: cache-key
env:
CACHE_VERSION: ${{ steps.cache-version.outputs.version }}
LIBC: ${{ matrix.libc || 'glibc' }}
shell: bash
run: |
# Cross-platform hash function.
if command -v shasum &> /dev/null; then
hash_cmd="shasum -a 256"
elif command -v sha256sum &> /dev/null; then
hash_cmd="sha256sum"
else
echo "Error: No SHA-256 command found"
exit 1
fi
# Hash a directory tree. Returns deterministic SHA over the
# concatenated file hashes. mkdir -p first so missing dirs
# (e.g. an empty patches/ that git didn't track) materialize
# rather than tripping set -e -o pipefail at the find call.
# Trailing || echo "" still covers the empty-tree case.
hash_dir() {
mkdir -p "$1"
(find "$1" -type f 2>/dev/null | LC_COLLATE=C sort -u | xargs $hash_cmd 2>/dev/null | $hash_cmd | cut -d' ' -f1) || echo ""
}
hash_file() {
($hash_cmd "$1" 2>/dev/null | cut -d' ' -f1) || echo ""
}
# Use libc-specific Dockerfile (glibc or musl) for Linux only.
# macOS/Windows don't use Docker.
DOCKERFILE_NAME="Dockerfile.${LIBC}"
DOCKERFILE_PATH="packages/boringssl-builder/docker/${DOCKERFILE_NAME}"
if [ -f "$DOCKERFILE_PATH" ]; then
DOCKERFILE_HASH=$($hash_cmd "$DOCKERFILE_PATH" | cut -d' ' -f1)
else
DOCKERFILE_HASH="no-docker"
fi
BIN_INFRA_LIB=$(hash_dir packages/bin-infra/lib)
BORINGSSL_PACKAGE_JSON=$(hash_file packages/boringssl-builder/package.json)
BORINGSSL_SUBMODULE_SHA=$(git ls-tree HEAD packages/boringssl-builder/upstream/boringssl 2>/dev/null | awk '{print $3}' || echo "")
BUILD_INFRA_EXTERNAL_TOOLS=$(hash_file packages/build-infra/external-tools.json)
BUILD_INFRA_LIB=$(hash_dir packages/build-infra/lib)
BUILD_INFRA_SCRIPTS=$(hash_dir packages/build-infra/scripts)
BUILD_SCRIPTS_HASH=$(hash_dir packages/boringssl-builder/scripts)
MAKE_HASH=$(hash_dir packages/boringssl-builder/make)
NODE_VERSION_HASH=$(hash_file .node-version)
PATCHES_HASH=$(hash_dir packages/boringssl-builder/patches)
PNPM_LOCK_HASH=$(hash_file pnpm-lock.yaml)
PNPM_WORKSPACE=$(hash_file pnpm-workspace.yaml)
ROOT_PACKAGE_JSON=$(hash_file package.json)
WORKFLOW_FILE="${GITHUB_WORKFLOW_REF%@*}"
WORKFLOW_FILE="${WORKFLOW_FILE#${GITHUB_REPOSITORY}/}"
SOCKET_REGISTRY_SHA=$(grep -ohE 'SocketDev/socket-registry/[^@]+@[0-9a-f]{40}' "$WORKFLOW_FILE" 2>/dev/null | head -1 | grep -oE '[0-9a-f]{40}$' || echo "")
FINAL_HASH=$(echo "${CACHE_VERSION}${DOCKERFILE_HASH}${BUILD_SCRIPTS_HASH}${PATCHES_HASH}${MAKE_HASH}${BUILD_INFRA_LIB}${BIN_INFRA_LIB}${BUILD_INFRA_EXTERNAL_TOOLS}${BUILD_INFRA_SCRIPTS}${PNPM_LOCK_HASH}${NODE_VERSION_HASH}${BORINGSSL_SUBMODULE_SHA}${LIBC}${ROOT_PACKAGE_JSON}${PNPM_WORKSPACE}${BORINGSSL_PACKAGE_JSON}${SOCKET_REGISTRY_SHA}" | $hash_cmd | cut -d' ' -f1)
echo "cache_version=${CACHE_VERSION}" >> $GITHUB_OUTPUT
echo "final_hash=${FINAL_HASH}" >> $GITHUB_OUTPUT
echo "Cache key hash: ${FINAL_HASH}"
- name: Set build mode
id: build-mode
uses: ./.github/actions/set-build-mode
with:
build-mode: ${{ inputs['build-mode'] }}
- name: Set platform-arch for cache
id: platform-arch-cache
uses: ./.github/actions/set-platform-arch
with:
platform: ${{ matrix.platform }}
arch: ${{ matrix.arch }}
libc: ${{ matrix.libc }}
- name: Compute boringssl paths
id: paths
shell: bash
env:
BUILD_MODE: ${{ steps.build-mode.outputs.mode }}
PLATFORM_ARCH: ${{ steps.platform-arch-cache.outputs.platform_arch }}
run: |
PACKAGE_DIR="packages/boringssl-builder"
MODE_BUILD_DIR="${PACKAGE_DIR}/build/${BUILD_MODE}"
PLATFORM_BUILD_DIR="${MODE_BUILD_DIR}/${PLATFORM_ARCH}"
FINAL_DIR="${PLATFORM_BUILD_DIR}/out/Final"
BORINGSSL_DIR="${FINAL_DIR}"
CHECKPOINTS_DIR="${PLATFORM_BUILD_DIR}/checkpoints"
{
echo "package_dir=${PACKAGE_DIR}"
echo "mode_build_dir=${MODE_BUILD_DIR}"
echo "platform_build_dir=${PLATFORM_BUILD_DIR}"
echo "final_dir=${FINAL_DIR}"
echo "boringssl_dir=${BORINGSSL_DIR}"
echo "checkpoints_dir=${CHECKPOINTS_DIR}"
} >> "$GITHUB_OUTPUT"
- name: Restore BoringSSL checkpoint cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 (2026-05-15)
id: boringssl-checkpoint-cache
if: ${{ !inputs.force }}
with:
path: |
packages/boringssl-builder/build/shared/checkpoints
${{ steps.paths.outputs.checkpoints_dir }}
key: boringssl-checkpoints-${{ steps.cache-key.outputs.cache_version }}-${{ matrix.platform }}-${{ matrix.arch }}${{ matrix.libc && format('-{0}', matrix.libc) || '' }}-${{ steps.build-mode.outputs.mode }}-${{ steps.cache-key.outputs.final_hash }}
- name: Set checkpoint chain for build mode
id: checkpoint-chain
env:
BUILD_MODE: ${{ steps.build-mode.outputs.mode }}
shell: bash
run: |
CHAIN=$(node packages/boringssl-builder/scripts/get-checkpoint-chain.mts --$BUILD_MODE)
echo "checkpoint_chain=$CHAIN" >> $GITHUB_OUTPUT
CHECKPOINTS=$(echo "$CHAIN" | tr ',' ' ')
echo "checkpoints=$CHECKPOINTS" >> $GITHUB_OUTPUT
echo "Checkpoint chain for $BUILD_MODE mode: $CHAIN"
- name: Validate checkpoint cache integrity
id: validate-cache
if: steps.boringssl-checkpoint-cache.outputs.cache-hit == 'true'
uses: ./.github/actions/validate-checkpoints
with:
checkpoint-dirs: packages/boringssl-builder/build/shared/checkpoints:${{ steps.paths.outputs.checkpoints_dir }}
checkpoints: ${{ steps.checkpoint-chain.outputs.checkpoints }}
package-name: boringssl-builder
- name: Restore build output from checkpoint chain
id: restore-checkpoint
uses: ./.github/actions/restore-checkpoint
with:
package-name: 'boringssl-builder'
build-mode: ${{ steps.build-mode.outputs.mode }}
checkpoint-chain: ${{ steps.checkpoint-chain.outputs.checkpoint_chain }}
cache-hit: ${{ steps.boringssl-checkpoint-cache.outputs.cache-hit }}
cache-valid: ${{ steps.validate-cache.outputs.valid }}
platform-arch: ${{ steps.platform-arch-cache.outputs.platform_arch }}
- name: Initialize BoringSSL submodule
if: (steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') || steps.restore-checkpoint.outputs.build-required == 'true' || inputs.force
uses: ./.github/actions/init-submodules
with:
submodules: packages/boringssl-builder/upstream/boringssl
- name: Setup Depot CLI
if: matrix.os == 'linux' && (steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true' || steps.restore-checkpoint.outputs.build-required != 'false' || inputs.force)
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1 (2026-05-15)
with:
oidc: true
- name: Stage registry tool-checksums for Docker build context
if: |
matrix.os == 'linux' &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
shell: bash
run: |
mkdir -p .build-context
cp "$SOCKET_TOOL_CHECKSUMS_FILE" .build-context/registry-tools.json
- name: Build BoringSSL with Depot (Linux - offloads compute)
if: |
matrix.os == 'linux' &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0 (2026-05-15)
with:
project: 8fpj9495vw
platforms: linux/${{ matrix.arch == 'x64' && 'amd64' || matrix.arch }}
build-args: |
BUILD_MODE=${{ steps.build-mode.outputs.mode }}
PLATFORM_ARCH=${{ steps.platform-arch-cache.outputs.platform_arch }}
CACHE_VERSION=${{ steps.cache-version.outputs.version }}
no-cache: ${{ inputs.force == true }}
file: packages/boringssl-builder/docker/Dockerfile.${{ matrix.libc || 'glibc' }}
target: export
outputs: type=local,dest=packages/boringssl-builder/build
context: .
- name: Verify Depot build output (Linux)
if: |
matrix.os == 'linux' &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
shell: bash
env:
PLATFORM_BUILD_DIR: ${{ steps.paths.outputs.platform_build_dir }}
BORINGSSL_DIR: ${{ steps.paths.outputs.boringssl_dir }}
PACKAGE_DIR: ${{ steps.paths.outputs.package_dir }}
BUILD_MODE: ${{ steps.build-mode.outputs.mode }}
run: |
echo "Verifying Depot build output structure..."
ls -lah "${PLATFORM_BUILD_DIR}/" || ls -lah "${PACKAGE_DIR}/build/${BUILD_MODE}/"
# Both libsmol_crypto.a + libsmol_ssl.a must be present.
if [ -f "${BORINGSSL_DIR}/lib/libsmol_crypto.a" ] && [ -f "${BORINGSSL_DIR}/lib/libsmol_ssl.a" ]; then
echo "✅ libsmol_crypto.a + libsmol_ssl.a found"
elif [ -f "${BORINGSSL_DIR}/lib/smol_crypto.lib" ] && [ -f "${BORINGSSL_DIR}/lib/smol_ssl.lib" ]; then
echo "✅ smol_crypto.lib + smol_ssl.lib found"
else
echo "× BoringSSL libs not found!"
echo "Contents of output directory:"
find "${PACKAGE_DIR}/build/${BUILD_MODE}/" -type f 2>/dev/null || echo "No files found"
exit 1
fi
- name: Setup build toolchain (macOS)
if: |
matrix.os == 'macos' &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
shell: bash
run: |
for i in 1 2 3; do
if brew install cmake ccache go; then
break
fi
if [ "$i" -eq 3 ]; then
echo "× brew install failed after 3 attempts"
exit 1
fi
echo "Attempt $i failed, retrying in 10 seconds..."
sleep 10
done
- name: Setup build toolchain (Windows x64)
if: |
matrix.os == 'windows' && !matrix.cross_compile &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
shell: bash
run: |
for i in 1 2 3; do
if choco install cmake mingw ccache golang -y; then
break
fi
echo "Attempt $i failed, retrying in 10 seconds..."
sleep 10
done
- name: Setup build toolchain (Windows ARM64 cross-compile)
if: |
matrix.os == 'windows' && matrix.cross_compile &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
shell: bash
run: |
for i in 1 2 3; do
if choco install cmake ccache golang -y; then
break
fi
echo "Attempt $i failed, retrying in 10 seconds..."
sleep 10
done
- name: Install llvm-mingw (Windows ARM64 cross-compile)
if: |
matrix.os == 'windows' && matrix.cross_compile &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
uses: ./.github/actions/install-llvm-mingw
- name: Build BoringSSL native (macOS/Windows)
if: |
matrix.os != 'linux' &&
((steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true')
shell: bash
env:
BUILD_MODE: ${{ steps.build-mode.outputs.mode }}
TARGET_ARCH: ${{ matrix.arch }}
run: |
cd packages/boringssl-builder
pnpm run build
- name: Debug build output structure
if: |
(steps.boringssl-checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.valid != 'true') ||
steps.restore-checkpoint.outputs.build-required == 'true'
shell: bash
env:
PLATFORM_BUILD_DIR: ${{ steps.paths.outputs.platform_build_dir }}
PACKAGE_DIR: ${{ steps.paths.outputs.package_dir }}
BUILD_MODE: ${{ steps.build-mode.outputs.mode }}
run: |
echo "Checking build output structure..."
echo "Contents of ${PLATFORM_BUILD_DIR}/:"
ls -lah "${PLATFORM_BUILD_DIR}/" || echo "Build directory does not exist"
echo ""
echo "Searching for BoringSSL library files:"
find "${PACKAGE_DIR}/build/${BUILD_MODE}/" -name "libsmol_*.a" -o -name "smol_*.lib" 2>/dev/null || echo "No BoringSSL library files found"
echo ""
echo "Complete directory tree:"
find "${PACKAGE_DIR}/build/${BUILD_MODE}/" -type f 2>/dev/null || echo "No files found"
- name: Verify release artifacts
shell: bash
env:
BORINGSSL_DIR: ${{ steps.paths.outputs.boringssl_dir }}
run: |
node packages/boringssl-builder/scripts/verify-release.mts "$BORINGSSL_DIR"
- name: Create archive
shell: bash
env:
BORINGSSL_DIR: ${{ steps.paths.outputs.boringssl_dir }}
PLATFORM: ${{ matrix.platform }}
ARCH: ${{ matrix.arch }}
LIBC: ${{ matrix.libc }}
run: |
cd "$BORINGSSL_DIR"
# Canonical pnpm-style platform string (`win32`, not `win`)
# matches every downstream consumer (lsquic-infra,
# ensure-boringssl, node-smol-builder).
ARCHIVE_NAME="boringssl-${PLATFORM}-${ARCH}"
if [ "${LIBC}" = "musl" ]; then
ARCHIVE_NAME="${ARCHIVE_NAME}-musl"
fi
# Verify both static libs are present.
if [ -f "lib/libsmol_crypto.a" ] && [ -f "lib/libsmol_ssl.a" ]; then
: # Unix / MinGW form
elif [ -f "lib/smol_crypto.lib" ] && [ -f "lib/smol_ssl.lib" ]; then
: # MSVC form
else
echo "× Error: BoringSSL libs not found in $BORINGSSL_DIR/lib"
ls -la "lib/" 2>/dev/null || echo "(lib/ does not exist)"
exit 1
fi
# Write the tar.gz up to the mode build dir. cwd is $BORINGSSL_DIR
# = build/<mode>/<platform-arch>/out/Final/; 3 ups → build/<mode>/.
# (lief uses 4 ups because LIEF_DIR is out/Final/lief — one deeper.)
OUTPUT_PATH="../../../${ARCHIVE_NAME}.tar.gz"
echo "Creating archive: ${ARCHIVE_NAME}.tar.gz"
tar -czf "${OUTPUT_PATH}" \
lib/ \
include/
echo "✅ Archive created successfully"
- name: Set artifact name
shell: bash
env:
PLATFORM: ${{ matrix.platform }}
ARCH: ${{ matrix.arch }}
LIBC: ${{ matrix.libc }}
run: |
ARTIFACT_NAME="boringssl-${PLATFORM}-${ARCH}"
if [ "${LIBC}" = "musl" ]; then
ARTIFACT_NAME="${ARTIFACT_NAME}-musl"
fi
echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
- name: Verify archive exists
shell: bash
env:
MODE_BUILD_DIR: ${{ steps.paths.outputs.mode_build_dir }}
ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }}
run: |
ARCHIVE_PATH="${MODE_BUILD_DIR}/${ARTIFACT_NAME}.tar.gz"
if [ ! -f "$ARCHIVE_PATH" ]; then
echo "× Archive not found at: $ARCHIVE_PATH"
echo "Contents of build directory:"
ls -lah "${MODE_BUILD_DIR}/" || echo "Build directory does not exist"
exit 1
fi
echo "✅ Archive found: $ARCHIVE_PATH"
ls -lh "$ARCHIVE_PATH"
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 (2026-05-15)
with:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ steps.paths.outputs.mode_build_dir }}/${{ env.ARTIFACT_NAME }}.tar.gz
retention-days: 30
if-no-files-found: error
compression-level: 0
release:
name: Release BoringSSL
needs: build-boringssl
if: github.event_name == 'workflow_dispatch' && !inputs['dry-run']
environment: release
permissions:
contents: write # Required to create GitHub releases
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 (2026-05-15)
with:
persist-credentials: false
sparse-checkout: |
.gitmodules
.github/scripts/generate-version.sh
sparse-checkout-cone-mode: false
- name: Download all artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 (2026-05-15)
with:
path: artifacts
pattern: boringssl-*
merge-multiple: true
- name: Verify downloaded artifacts
shell: bash
run: |
echo "Checking for downloaded artifacts..."
if [ -d "artifacts" ]; then
echo "✅ Artifacts directory exists"
echo "Contents:"
ls -lah artifacts/
if [ -n "$(ls -A artifacts/*.tar.gz 2>/dev/null)" ]; then
echo "✅ Found $(ls artifacts/*.tar.gz 2>/dev/null | wc -l) tar.gz files"
else
echo "× No tar.gz files found in artifacts directory"
exit 1
fi
else
echo "× Artifacts directory does not exist"
echo "This means no artifacts were uploaded by the build jobs."
exit 1
fi
- name: Get BoringSSL version
id: version
shell: bash
run: |
# Extract version from .gitmodules comment (canonical source).
# Form is `# boringssl-YYYY-MM-DD via bun-vX.Y.Z` per the
# date-via-downstream extension to gitmodules-version-comments.
BORINGSSL_VERSION=$(grep -B 1 'packages/boringssl-builder/upstream/boringssl' .gitmodules | grep '# boringssl-' | sed 's/.*# boringssl-//' | sed 's/ via .*//')
if [ -z "$BORINGSSL_VERSION" ]; then
echo "Error: Failed to extract BoringSSL version from .gitmodules"
exit 1
fi
echo "version=${BORINGSSL_VERSION}" >> $GITHUB_OUTPUT
echo "BoringSSL version: ${BORINGSSL_VERSION}"
- name: Generate release tag
id: tag
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
source .github/scripts/generate-version.sh
TAG="boringssl-${VERSION}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "Release tag: ${TAG}"
if gh release view "$TAG" &>/dev/null; then
echo "Release $TAG already exists, skipping."
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: Create GitHub Release
if: steps.tag.outputs.skip != 'true'
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ steps.tag.outputs.tag }}
BORINGSSL_VERSION: ${{ steps.version.outputs.version }}
shell: bash
run: |
mkdir -p release
for file in artifacts/*.tar.gz; do
if [ -f "$file" ]; then
mv "$file" release/
fi
done
if [ -z "$(ls -A release/*.tar.gz 2>/dev/null)" ]; then
echo "Error: No .tar.gz files found in release directory after moving from artifacts"
exit 1
fi
echo "Found $(ls release/*.tar.gz | wc -l) archives to release"
cd release
if command -v shasum &> /dev/null; then
shasum -a 256 *.tar.gz > checksums.txt
elif command -v sha256sum &> /dev/null; then
sha256sum *.tar.gz > checksums.txt
else
echo "Error: No SHA-256 command found"
exit 1
fi
cat checksums.txt
cd ..
TITLE_SUFFIX="${RELEASE_TAG#boringssl-}"
# Immutable-releases 3-step: draft → upload → publish.
# Single-call form races the Sigstore attestation hash.
# See docs/claude.md/fleet/immutable-releases.md.
gh release create "${RELEASE_TAG}" \
--draft \
--title "boringssl ${TITLE_SUFFIX}" \
--notes "BoringSSL (prefixed: smol_*) static libraries for node:smol-http transport stack.
## Platforms
- darwin-arm64
- darwin-x64
- linux-arm64
- linux-x64
- linux-arm64-musl
- linux-x64-musl
- win32-arm64
- win32-x64
## Files
Each platform archive contains:
- Static libraries (\`lib/libsmol_crypto.a\` + \`lib/libsmol_ssl.a\`, or \`smol_crypto.lib\` + \`smol_ssl.lib\` on MSVC)
- Header files (\`include/openssl/*.h\`)
- \`checksums.txt\` - SHA256 checksums
Symbols are prefixed via \`-DBORINGSSL_PREFIX=smol\` so the libs link cleanly alongside Node's bundled OpenSSL with zero symbol collisions. Pinned to the same SHA Bun ships in v${BORINGSSL_VERSION}.
## Usage
Download the appropriate archive for your platform and extract:
\`\`\`sh
tar -xzf boringssl-<platform>-<arch>.tar.gz
# Or for musl:
tar -xzf boringssl-<platform>-<arch>-musl.tar.gz
\`\`\`"
gh release upload "${RELEASE_TAG}" \
release/*.tar.gz \
release/checksums.txt
gh release edit "${RELEASE_TAG}" --draft=false
update-checksums:
needs: release
if: github.event_name == 'workflow_dispatch' && !inputs['dry-run']
permissions:
contents: write # release-assets.json commit after publishing GitHub release
uses: ./.github/workflows/update-checksums.yml
secrets:
BOT_GPG_PRIVATE_KEY: ${{ secrets.BOT_GPG_PRIVATE_KEY }}