Skip to content

Application experience improvements #607

Application experience improvements

Application experience improvements #607

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
timeout-minutes: 5
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
bun-ecosystem:
name: Bun Ecosystem Checks
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Verify bun.lock hash integrity
run: |
set -euo pipefail
stored="$(bun pm hash-print | tr -d '\r\n')"
computed="$(bun pm hash | tr -d '\r\n')"
if [ -z "${stored}" ] || [ -z "${computed}" ]; then
echo "Failed to compute bun.lock hash."
exit 1
fi
if [ "${stored}" != "0000000000000000-0000000000000000-0000000000000000-0000000000000000" ] && [ "${stored}" != "${computed}" ]; then
echo "bun.lock hash mismatch."
echo "stored: ${stored}"
echo "computed: ${computed}"
exit 1
fi
git diff --exit-code -- bun.lock
- name: Audit dependencies
run: bun audit --audit-level=high
marketplace-validate:
name: Marketplace Packer Validate
runs-on: ubuntu-latest
timeout-minutes: 5
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
compose-validate:
name: Compose File Validate
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
- name: Validate docker-compose.yml
run: docker compose config --quiet
docker-context-guard:
name: Docker Context Guard
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Use docker/build-push-action with GHA + registry cache so unchanged
# layers are reused across CI runs (~3 min → ~30s on cache hit).
# Previously this ran a bare `docker build` with no caching at all.
- name: Build Docker target stage
uses: docker/build-push-action@v6
with:
context: .
file: packages/core/src/docker/Dockerfile
target: opencode-build
push: false
load: false
cache-from: |
type=gha,scope=opencode-cloud-sandbox-context-guard,version=2
type=gha,scope=opencode-cloud-sandbox-amd64,version=2
type=registry,ref=ghcr.io/prizz/opencode-cloud-sandbox:buildcache-amd64
cache-to: type=gha,scope=opencode-cloud-sandbox-context-guard,mode=min,version=2
# 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 }}
timeout-minutes: 20
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 -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: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: '20'
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Rust cache
uses: Swatinem/rust-cache@v2
- name: Configure git identity
run: |
git config --global user.email "bot@opencode.ai"
git config --global user.name "opencode"
# 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
timeout-minutes: 5
needs: [build]
steps:
- uses: actions/checkout@v6
- name: Install just
uses: extractions/setup-just@v3
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: '20'
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
install: "false"
- 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: bun run --cwd packages/cli-node test
# E2E Tests - Playwright browser tests for the opencode web UI
e2e:
name: E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 30
needs: [build]
steps:
- uses: actions/checkout@v6
- name: Initialize opencode submodule
run: |
git -c url."https://github.com/".insteadOf=git@github.com: submodule update --init --recursive packages/opencode
git submodule status --recursive
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: '20'
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
install: "false"
- name: Configure git identity
run: |
git config --global user.email "bot@opencode.ai"
git config --global user.name "opencode"
- name: Install just
uses: extractions/setup-just@v3
- name: Run e2e tests
run: just ci-e2e
timeout-minutes: 30
- name: Upload Playwright artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-e2e-${{ github.run_attempt }}
if-no-files-found: ignore
retention-days: 7
path: |
packages/opencode/packages/app/e2e/test-results
packages/opencode/packages/app/e2e/playwright-report