Skip to content
Open
36 changes: 36 additions & 0 deletions .github/actions/build-package/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Build and package (Bun -> single zip)
description: Build with Bun (Turbo) and package a single distributable archive
outputs:
archive_path:
description: Absolute path to the archive
value: ${{ steps.pkg.outputs.archive_path }}
runs:
using: composite
steps:
- name: Setup Bun (from .bun-version)
uses: ./.github/actions/setup-bun

- name: Build (Turbo)
shell: bash
run: |
if ! OPENCODE_CHANNEL=latest bunx turbo run build --env-mode=loose; then
echo "Turbo build failed; continuing with source packaging for security scan."
fi

- name: Ensure zip is available
shell: bash
run: sudo apt-get update -y && sudo apt-get install -y zip

- name: Package single file
id: pkg
shell: bash
run: |
set -e
mkdir -p bundle
if [ -d dist ]; then SRC=dist; elif [ -d build ]; then SRC=build; else SRC=.; fi
if [ "$SRC" = "." ]; then
zip -r bundle/opencode.zip . -x '.git/*' '.github/*' 'node_modules/*'
else
(cd "$SRC" && zip -r ../bundle/opencode.zip .)
fi
echo "archive_path=$(pwd)/bundle/opencode.zip" >> "$GITHUB_OUTPUT"
82 changes: 82 additions & 0 deletions .github/workflows/clam-av.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: av-clamav
on:
release:
types: [published]
workflow_dispatch:

permissions:
contents: read
actions: read

jobs:
clamav:
runs-on: ubuntu-latest
steps:
# Checkout the right ref
- name: Checkout (release tag)
if: github.event_name == 'release'
uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- name: Checkout (PR/default)
if: github.event_name != 'release'
uses: actions/checkout@v4

# Single source-of-truth build -> one file
- name: Build and package
id: build
uses: ./.github/actions/build-package

# Install fresh ClamAV DB
- name: Install & update ClamAV DB
run: |
set -e
sudo apt-get update
sudo apt-get install -y clamav clamav-freshclam unzip
sudo systemctl stop clamav-freshclam || true
sudo mkdir -p /var/lib/clamav
sudo chown -R clamav:clamav /var/lib/clamav
sudo freshclam --verbose
ls -lh /var/lib/clamav

# Scan extracted bundle so counts reflect actual files
- name: Verify ClamAV detects EICAR signature
run: |
set -euo pipefail
printf 'X5O!P%%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > eicar.com
status=0
clamscan eicar.com > eicar.log || status=$?
cat eicar.log
if [ "$status" -ne 1 ]; then
echo "ClamAV failed to report the EICAR signature" >&2
exit 1
fi
grep -q 'eicar.com: Eicar-Test-Signature FOUND' eicar.log
grep -q 'Infected files: 1' eicar.log
rm -f eicar.com eicar.log

- name: Extract bundle and scan
run: |
set -euo pipefail
rm -rf scan && mkdir -p scan
unzip -q bundle/opencode.zip -d scan
echo "File count in payload: $(find scan -type f | wc -l)"
clamscan -ri --scan-archive=yes scan | tee clamav.log
if grep -qE 'Infected files: [1-9][0-9]*' clamav.log; then
findings=$(grep 'FOUND' clamav.log | grep -v 'Eicar-Test-Signature' || true)
if [ -n "${findings}" ]; then
echo "Unexpected detections found:" >&2
echo "${findings}" >&2
exit 1
fi
echo 'Only EICAR detections observed; continuing.'
fi

- name: Upload scan results
if: ${{ env.ACTIONS_RUNTIME_TOKEN != '' }}
uses: actions/upload-artifact@v4
with:
name: clamav-scan-results
path: |
clamav.log
bundle/opencode.zip
74 changes: 74 additions & 0 deletions .github/workflows/dependency-security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: dependency-security
on:
pull_request:
release:
types: [published]
workflow_dispatch:

permissions:
contents: read

jobs:
bun-audit:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

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

- name: Run Bun audit (prod, high+)
run: bun audit --prod --audit-level=high

trivy-release:
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Checkout (release tag)
if: github.event_name == 'release'
uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- name: Checkout (default)
if: github.event_name != 'release'
uses: actions/checkout@v4

- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@0.34.1
with:
version: v0.69.1
scan-type: fs
scan-ref: .
scanners: vuln
vuln-type: library
severity: HIGH,CRITICAL
ignore-unfixed: true
format: sarif
output: trivy-results.sarif
exit-code: "1"

- name: Run Trivy misconfig and secret scan
uses: aquasecurity/trivy-action@0.34.1
with:
version: v0.69.1
scan-type: fs
scan-ref: .
scanners: misconfig,secret
severity: HIGH,CRITICAL
skip-dirs: node_modules,packages/opencode/dist,tree-sitter-scheme
format: sarif
output: trivy-policy-results.sarif
exit-code: "0"

- name: Upload Trivy report
if: ${{ always() && env.ACTIONS_RUNTIME_TOKEN != '' }}
uses: actions/upload-artifact@v4
with:
name: trivy-release-report
path: |
trivy-results.sarif
trivy-policy-results.sarif
Loading