Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions .github/workflows/codeq-gcs-upload.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
name: Upload CodeQ to GCS

on:
workflow_dispatch:
inputs:
version:
description: "Version tag (e.g., v1.0.0). Leave empty to use current timestamp."
required: false
type: string

jobs:
build:
name: Build CodeQ binaries
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: linux-x64
build-os: linux
build-arch: x64
- os: ubuntu-latest
target: linux-arm64
build-os: linux
build-arch: arm64
- os: macos-latest
target: darwin-x64
build-os: darwin
build-arch: x64
- os: macos-latest
target: darwin-arm64
build-os: darwin
build-arch: arm64
- os: windows-latest
target: windows-x64
build-os: win32
build-arch: x64

runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json

- name: Cache ~/.bun
uses: actions/cache@v4
with:
path: ~/.bun
key: ${{ runner.os }}-bun-${{ hashFiles('package.json') }}-${{ hashFiles('bun.lockb', 'bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-${{ hashFiles('package.json') }}-

- name: Install dependencies
run: bun install

- name: Apply qBraid branding
run: bun branding/apply.ts qbraid

- name: Build CodeQ binary
run: |
cd packages/opencode
bun run build --single
env:
CODEQ_VERSION: ${{ inputs.version || '' }}

- name: List build artifacts
run: ls -la packages/opencode/dist/
shell: bash

- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: codeq-${{ matrix.target }}
path: packages/opencode/dist/codeq-*/
if-no-files-found: error

deploy:
name: Upload to GCS
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
id-token: write

env:
GCP_PROJECT_ID: qbraid-prod
GCS_BUCKET: qbraid-codeq
WORKLOAD_IDENTITY_PROVIDER: projects/314301605548/locations/global/workloadIdentityPools/github-actions-v2-pool/providers/github-oidc-v2
SERVICE_ACCOUNT: github-actions-v2-deploy@qbraid-prod.iam.gserviceaccount.com

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Authenticate with Google Cloud
id: auth
uses: google-github-actions/auth@v2
with:
token_format: access_token
workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ env.SERVICE_ACCOUNT }}

- name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@v2

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Determine version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION="dev-$(date +%Y%m%d-%H%M%S)"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Using version: $VERSION"

- name: Prepare binaries for upload
run: |
mkdir -p upload
VERSION="${{ steps.version.outputs.version }}"

# Process each artifact
for artifact_dir in artifacts/codeq-*/; do
if [ -d "$artifact_dir" ]; then
# Find the binary directory inside
for bin_dir in "$artifact_dir"codeq-*/; do
if [ -d "$bin_dir" ]; then
# Extract target name from directory
dirname=$(basename "$bin_dir")
# e.g., codeq-darwin-arm64 -> darwin-arm64
target=${dirname#codeq-}

# Create versioned path
mkdir -p "upload/$VERSION/$target"

# Copy binaries
if [ -f "$bin_dir/bin/codeq" ]; then
cp "$bin_dir/bin/codeq" "upload/$VERSION/$target/"
elif [ -f "$bin_dir/bin/codeq.exe" ]; then
cp "$bin_dir/bin/codeq.exe" "upload/$VERSION/$target/"
fi

# Copy package.json if exists
if [ -f "$bin_dir/package.json" ]; then
cp "$bin_dir/package.json" "upload/$VERSION/$target/"
fi
fi
done
fi
done

# Show what we're uploading
echo "Files to upload:"
find upload -type f

- name: Upload binaries to GCS
run: |
VERSION="${{ steps.version.outputs.version }}"

# Upload versioned binaries
gsutil -m cp -r "upload/$VERSION" "gs://${{ env.GCS_BUCKET }}/"

# If this is a release version (starts with v), also update latest
if [[ "$VERSION" == v* ]]; then
echo "Updating latest symlinks..."
gsutil -m rm -rf "gs://${{ env.GCS_BUCKET }}/latest" || true
gsutil -m cp -r "upload/$VERSION" "gs://${{ env.GCS_BUCKET }}/latest"
fi

- name: Verify upload
run: |
VERSION="${{ steps.version.outputs.version }}"
echo "Listing contents of gs://${{ env.GCS_BUCKET }}/$VERSION/:"
gsutil ls -r "gs://${{ env.GCS_BUCKET }}/$VERSION/"

echo ""
echo "Download URLs:"
for target in darwin-arm64 darwin-x64 linux-arm64 linux-x64 windows-x64; do
echo " $target: https://storage.googleapis.com/${{ env.GCS_BUCKET }}/$VERSION/$target/codeq"
done

- name: Create version manifest
run: |
VERSION="${{ steps.version.outputs.version }}"
cat > manifest.json << EOF
{
"version": "$VERSION",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"binaries": {
"darwin-arm64": "https://storage.googleapis.com/${{ env.GCS_BUCKET }}/$VERSION/darwin-arm64/codeq",
"darwin-x64": "https://storage.googleapis.com/${{ env.GCS_BUCKET }}/$VERSION/darwin-x64/codeq",
"linux-arm64": "https://storage.googleapis.com/${{ env.GCS_BUCKET }}/$VERSION/linux-arm64/codeq",
"linux-x64": "https://storage.googleapis.com/${{ env.GCS_BUCKET }}/$VERSION/linux-x64/codeq",
"windows-x64": "https://storage.googleapis.com/${{ env.GCS_BUCKET }}/$VERSION/windows-x64/codeq.exe"
}
}
EOF

gsutil cp manifest.json "gs://${{ env.GCS_BUCKET }}/$VERSION/manifest.json"

# Update latest manifest for release versions
if [[ "$VERSION" == v* ]]; then
gsutil cp manifest.json "gs://${{ env.GCS_BUCKET }}/latest/manifest.json"
fi

echo "Manifest uploaded:"
cat manifest.json
171 changes: 171 additions & 0 deletions branding/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# OpenCode Branding System

White-label opencode for your organization. This system applies branding transformations at build time, making it maintainable across opencode updates.

## Quick Start

```bash
# Preview changes
bun branding/apply.ts qbraid --dry-run

# Apply branding
bun branding/apply.ts qbraid

# Build
cd packages/opencode && bun run build

# Test
./dist/codeq-darwin-arm64/bin/codeq --help
```

## What Gets Branded

| Component | Original | Branded (qBraid) |
| --------- | -------------------------- | ----------------------- |
| Binary | `opencode` | `codeq` |
| CLI Logo | "open code" | "code q" (purple Q) |
| Env Vars | `OPENCODE_*` | `CODEQ_*` |
| App Dir | `~/.local/share/opencode/` | `~/.local/share/codeq/` |
| Models | models.dev + all providers | qBraid provider only |

## Directory Structure

```
branding/
├── apply.ts # Branding script
├── schema.ts # Configuration schema
├── README.md
└── qbraid/
├── brand.json # Brand configuration
└── models.json # Custom model definitions
```

## Creating a New Brand

1. Create directory: `mkdir branding/mybrand`

2. Create `brand.json`:

```json
{
"version": 1,
"id": "mybrand",
"name": "My Brand",
"logo": {
"cli": [
["left1", "right1"],
["left2", "right2"],
["left3", "right3"],
["left4", "right4"]
],
"tui": {
"left": ["row1", "row2", "row3", "row4"],
"right": ["row1", "row2", "row3", "row4"]
}
},
"replacements": {
"productName": "mybrand",
"displayName": "MyBrand",
"binaryName": "mybrand",
"envPrefix": "MYBRAND",
"appDir": "mybrand"
},
"models": {
"exclusive": true,
"source": "./models.json"
}
}
```

3. Create `models.json` with your providers (see `qbraid/models.json` for format)

4. Apply: `bun branding/apply.ts mybrand`

## Updating to New OpenCode Versions

```bash
# 1. Pull latest
git fetch upstream && git merge upstream/dev

# 2. Re-apply branding
bun branding/apply.ts qbraid

# 3. Fix any conflicts, build and test
cd packages/opencode && bun run build
./dist/codeq-darwin-arm64/bin/codeq --version
```

## Safe Testing Workflow

Use a git worktree to test without affecting your main checkout:

```bash
git worktree add ../opencode-brand-test HEAD
cp -r branding ../opencode-brand-test/
cd ../opencode-brand-test
bun install
bun branding/apply.ts qbraid
cd packages/opencode && bun run build --single
./dist/codeq-darwin-arm64/bin/codeq --help

# Cleanup
cd ../opencode && git worktree remove ../opencode-brand-test
```

## Configuration Reference

### `brand.json`

| Field | Required | Description |
| -------------------------- | -------- | -------------------------------------------- |
| `version` | Yes | Schema version (must be `1`) |
| `id` | Yes | Brand identifier |
| `name` | Yes | Display name |
| `logo.cli` | Yes | CLI banner (4 rows of [left, right] tuples) |
| `logo.tui` | Yes | TUI logo with shadow markers (`_`, `^`, `~`) |
| `replacements.productName` | Yes | Lowercase name for code |
| `replacements.displayName` | Yes | Proper-cased name for UI |
| `replacements.binaryName` | Yes | CLI command name |
| `replacements.envPrefix` | Yes | Environment variable prefix |
| `replacements.appDir` | Yes | XDG directory name |
| `models.exclusive` | No | If true, only use defined providers |
| `models.source` | No | Path to models.json |
| `skipFiles` | No | Glob patterns to skip |
| `patches` | No | Custom file patches |

### `models.json`

```json
{
"provider-id": {
"id": "provider-id",
"name": "Provider Name",
"env": ["API_KEY_VAR"],
"npm": "@ai-sdk/provider",
"api": "https://api.example.com/v1",
"models": {
"model-id": {
"id": "model-id",
"name": "Model Name",
"family": "model-family",
"release_date": "2025-01-01",
"attachment": true,
"reasoning": true,
"temperature": true,
"tool_call": true,
"cost": { "input": 3, "output": 15 },
"limit": { "context": 200000, "output": 16000 },
"options": {}
}
}
}
}
```

## Troubleshooting

**"oldString not found"**: Upstream code changed. Update the transform in `apply.ts`.

**Models not showing**: Models only appear when their provider has credentials set (e.g., `QBRAID_API_KEY`).

**Build fails**: Check that `@opencode-ai/*` workspace imports weren't accidentally renamed.
Loading
Loading