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
145 changes: 145 additions & 0 deletions .github/workflows/opencode-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Opencode Smoke

on:
workflow_dispatch:
inputs:
tag:
description: 'npm dist-tag to test'
required: true
default: next
timeout:
description: 'seconds to wait before considering opencode stable'
required: false
default: '30'
workflow_call:
inputs:
tag:
type: string
required: true
timeout:
type: number
required: false
default: 30

jobs:
smoke:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Resolve plugin version
id: version
run: |
VERSION=$(npm view opencode-synced@${{ inputs.tag }} version)
if [ -z "$VERSION" ]; then
echo "No version found for tag: ${{ inputs.tag }}"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Install opencode
env:
OPENCODE_INSTALL_DIR: ${{ runner.temp }}/opencode/bin
run: |
curl -fsSL https://opencode.ai/install | bash
echo "${OPENCODE_INSTALL_DIR}" >> "$GITHUB_PATH"

- name: Configure clean opencode home
env:
OPENCODE_HOME: ${{ runner.temp }}/opencode-home
PLUGIN_VERSION: ${{ steps.version.outputs.version }}
run: |
export HOME="$OPENCODE_HOME"
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_STATE_HOME="$HOME/.local/state"

mkdir -p "$XDG_CONFIG_HOME/opencode"
cat > "$XDG_CONFIG_HOME/opencode/opencode.json" <<EOF
{
"\$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-synced@${PLUGIN_VERSION}"]
}
EOF

rm -rf "$XDG_CACHE_HOME/opencode/node_modules"

- name: Launch opencode (smoke)
env:
OPENCODE_HOME: ${{ runner.temp }}/opencode-home
OPENCODE_SMOKE_TIMEOUT: ${{ inputs.timeout }}
OPENCODE_SMOKE_LOG: ${{ runner.temp }}/opencode-smoke.log
run: |
export HOME="$OPENCODE_HOME"
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_STATE_HOME="$HOME/.local/state"

python - <<'PY'
import os
import threading
import subprocess
import time
import sys

timeout = int(os.environ.get("OPENCODE_SMOKE_TIMEOUT", "20"))
log_path = os.environ.get("OPENCODE_SMOKE_LOG", "opencode-smoke.log")
cmd = ["opencode", "serve", "--port", "4096", "--hostname", "127.0.0.1"]

proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
)

def reader():
if not proc.stdout:
return
with open(log_path, "w") as log_file:
for line in proc.stdout:
log_file.write(line)

thread = threading.Thread(target=reader, daemon=True)
thread.start()

start = time.time()
while time.time() - start < timeout:
if proc.poll() is not None:
break
time.sleep(1)

if proc.poll() is not None:
print("opencode exited early with code", proc.returncode)
try:
with open(log_path, "r") as log_file:
lines = log_file.readlines()
tail = "".join(lines[-200:])
print("--- opencode output (tail) ---")
print(tail)
except FileNotFoundError:
print("No log output captured.")
sys.exit(1)

proc.terminate()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
proc.kill()
proc.wait()
PY

- name: Upload opencode logs (on failure)
if: failure()
uses: actions/upload-artifact@v4
with:
name: opencode-smoke-logs-${{ matrix.os }}
path: ${{ runner.temp }}/opencode-smoke.log
57 changes: 54 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ permissions:
jobs:
publish:
runs-on: ubuntu-latest
outputs:
requested_tag: ${{ steps.publish.outputs.requested_tag }}
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4

Expand All @@ -38,12 +41,60 @@ jobs:
- id: inputs
uses: simenandre/setup-inputs@v1

- name: Publish to npm with OIDC
- name: Publish candidate to npm with OIDC
id: publish
run: |
TAG="${{ steps.inputs.outputs.tag }}"
if [ -z "$TAG" ]; then
TAG="latest"
fi

echo "Publishing with tag: $TAG"
mise run publish --tag "$TAG"
echo "requested_tag=$TAG" >> "$GITHUB_OUTPUT"

CANDIDATE_TAG="next"
echo "Publishing candidate with tag: $CANDIDATE_TAG (requested: $TAG)"
mise run publish --tag "$CANDIDATE_TAG"

- name: Resolve published version
id: version
run: |
VERSION=$(npm view opencode-synced@next version)
if [ -z "$VERSION" ]; then
echo "Failed to resolve version from npm tag: next"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

smoke:
needs: publish
uses: ./.github/workflows/opencode-smoke.yml
with:
tag: next
timeout: 20

promote_latest:
needs: [publish, smoke]
if: needs.publish.outputs.requested_tag == 'latest'
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4

- uses: jdx/mise-action@d6e32c1796099e0f1f3ac741c220a8b7eae9e5dd
with:
install: true
cache: true
experimental: true

- name: Promote latest dist-tag
run: |
VERSION="${{ needs.publish.outputs.version }}"
if [ -z "$VERSION" ]; then
echo "Missing published version."
exit 1
fi

echo "Promoting opencode-synced@$VERSION to latest"
npm dist-tag add "opencode-synced@$VERSION" latest
Loading