Skip to content

fix(docker): harden bun install retry cache handling #399

fix(docker): harden bun install retry cache handling

fix(docker): harden bun install retry cache handling #399

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# Formatting check - only needs to run once since cargo fmt is purely textual
# (no compilation, so no platform-specific code paths like #[cfg(target_os)])
format:
name: Format Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.89"
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
marketplace-validate:
name: Marketplace Packer Validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Assert Marketplace scripts
run: |
test -f infra/digitalocean/marketplace/90-cleanup.sh
test -f infra/digitalocean/marketplace/99-img-check.sh
- name: Setup Packer
uses: hashicorp/setup-packer@v3
with:
version: "1.10.0"
- name: Packer init
run: packer init infra/digitalocean/packer/opencode-marketplace.pkr.hcl
- name: Packer fmt
run: packer fmt -check infra/digitalocean/packer/opencode-marketplace.pkr.hcl
- name: Packer validate
run: packer validate -var-file=infra/digitalocean/packer/variables.pkr.hcl infra/digitalocean/packer/opencode-marketplace.pkr.hcl
docker-context-guard:
name: Docker Context Guard
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build Docker target stage
run: |
DOCKER_BUILDKIT=1 docker build \
--file packages/core/src/docker/Dockerfile \
--target opencode-build \
--tag opencode-cloud-sandbox:ci-check \
.
cargo-package-verify:
name: Cargo Package Verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Package opencode-cloud-core
run: cargo package -p opencode-cloud-core --allow-dirty
- name: Determine core version and publication status
id: core-publication
run: |
set -euo pipefail
core_version="$(python3 -c 'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("packages/core/Cargo.toml").read_text())["package"]["version"])')"
echo "core_version=${core_version}" >> "$GITHUB_OUTPUT"
if ./scripts/check-crate-version-published.sh opencode-cloud-core "${core_version}"; then
echo "published=true" >> "$GITHUB_OUTPUT"
else
check_exit=$?
if [ "${check_exit}" -eq 1 ]; then
echo "published=false" >> "$GITHUB_OUTPUT"
else
exit "${check_exit}"
fi
fi
- name: Package opencode-cloud (PR no-verify archive)
if: github.event_name == 'pull_request'
run: cargo package -p opencode-cloud --allow-dirty --no-verify
- name: Verify packaged opencode-cloud against local core (PR)
if: github.event_name == 'pull_request'
run: |
set -euo pipefail
crate_archive="$(ls -t target/package/opencode-cloud-*.crate | head -n1)"
if [ -z "${crate_archive}" ]; then
echo "Error: opencode-cloud package archive not found."
exit 1
fi
crate_basename="$(basename "${crate_archive}" .crate)"
unpack_dir="$(mktemp -d)"
config_file="$(mktemp)"
trap 'rm -rf "${unpack_dir}" "${config_file}"' EXIT
tar -xzf "${crate_archive}" -C "${unpack_dir}"
crate_dir="${unpack_dir}/${crate_basename}"
manifest_path="${crate_dir}/Cargo.toml"
if [ ! -f "${manifest_path}" ]; then
echo "Error: unpacked package manifest not found at ${manifest_path}"
exit 1
fi
cat > "${config_file}" <<EOF
[patch.crates-io]
opencode-cloud-core = { path = "${GITHUB_WORKSPACE}/packages/core" }
EOF
cargo check --manifest-path "${manifest_path}" --config "${config_file}"
- name: Package opencode-cloud (main push, published core)
if: github.event_name == 'push' && steps.core-publication.outputs.published == 'true'
run: cargo package -p opencode-cloud --allow-dirty
- name: Skip opencode-cloud package verify (main push, core unpublished)
if: github.event_name == 'push' && steps.core-publication.outputs.published != 'true'
run: |
echo "Skipping opencode-cloud packaging verify on main push."
echo "Reason: opencode-cloud-core ${{ steps.core-publication.outputs.core_version }} is not yet published on crates.io."
{
echo "## Cargo Package Verify"
echo ""
echo "Skipped \`cargo package -p opencode-cloud\` on push to main."
echo "Reason: dependency \`opencode-cloud-core ${{ steps.core-publication.outputs.core_version }}\` is not yet published on crates.io."
} >> "$GITHUB_STEP_SUMMARY"
# Build, lint, and test on multiple platforms
# Clippy/build/test must run on each platform because #[cfg(target_os)] causes
# different code to compile (e.g., systemd.rs on Linux, launchd.rs on macOS)
build:
name: Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v6
- name: Verify opencode submodule pin is published
run: ./scripts/check-opencode-submodule-published.sh
- name: Install Linux system dependencies
if: matrix.os == 'ubuntu-latest'
run: |
# Required by opencode-broker (libpam-sys links against -lpam).
sudo apt-get update
sudo apt-get install -y libpam0g-dev
- name: Initialize opencode submodule
run: |
git submodule sync --recursive
git -c url."https://github.com/".insteadOf=git@github.com: submodule update --init --recursive packages/opencode
git submodule status --recursive
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.89"
components: clippy
- name: Install just
uses: extractions/setup-just@v3
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: '20'
cache: 'pnpm'
- name: Install Bun
uses: oven-sh/setup-bun@v2
- name: Rust cache
uses: Swatinem/rust-cache@v2
- name: Install Node dependencies
run: just ci-node-install
# Project checks should run via shared just targets.
- name: Run CI checks
run: just ci-checks
- name: Record CLI parity SHA
if: matrix.os == 'ubuntu-latest'
run: git rev-parse HEAD > cli-parity.sha
- name: Upload CLI parity artifacts
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
name: cli-parity-artifacts
path: |
target/debug/opencode-cloud
packages/cli-node/dist
cli-parity.sha
# CLI Parity - ensures Node CLI can invoke all Rust CLI commands
cli-parity:
name: CLI Parity Tests
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v6
- name: Install just
uses: extractions/setup-just@v3
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: '20'
cache: 'pnpm'
- name: Download CLI parity artifacts
uses: actions/download-artifact@v4
with:
name: cli-parity-artifacts
- name: Verify artifact SHA
run: |
if [ -f cli-parity.sha ]; then
echo "Artifact SHA: $(cat cli-parity.sha)"
echo "Workflow SHA: $GITHUB_SHA"
test "$(cat cli-parity.sha)" = "$GITHUB_SHA"
fi
- name: Ensure Rust binary executable
run: chmod +x target/debug/opencode-cloud
- name: Install Node dependencies (cli only)
run: just ci-node-install-cli-only
- name: Run CLI parity tests
run: pnpm -C packages/cli-node test