diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..8e66913 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +.github/CODEOWNERS @djchen +.github/workflows/* @djchen +.github/dependabot.yml @djchen diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09bbc1e..10c2424 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,94 +4,13 @@ on: pull_request: branches: - main - push: - branches: - - main workflow_dispatch: permissions: contents: read jobs: - runtime-config-regression: - runs-on: ubuntu-latest - - steps: - - name: Check out repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - submodules: recursive - - - name: Build Docker image for regression checks - run: docker build -t opencode-web-docker . - - - name: Setup Bun - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 - - - name: Install dependencies - run: bun install --frozen-lockfile - - - name: Run runtime-config regression checks - run: bun run test:runtime-config - - build-compat-tests: - runs-on: ubuntu-latest - - steps: - - name: Check out repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - submodules: recursive - - - name: Setup Bun - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 - - - name: Install dependencies - run: bun install --frozen-lockfile - - - name: Run build-compat unit tests - run: bun test - - - name: Run upstream compatibility check - run: bun run test:compat - - - name: Run TypeScript typecheck - run: bun run typecheck - - - name: Run Biome lint - run: bun run lint - - - name: Check formatting - run: bun run format:check - - actionlint: - runs-on: ubuntu-latest - - steps: - - name: Check out repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - - name: Run actionlint - uses: rhysd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca # v1.7.12 - - shellcheck: - runs-on: ubuntu-latest - - steps: - - name: Check out repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - - name: Install ShellCheck - run: sudo apt-get update && sudo apt-get install -y shellcheck - - - name: Run ShellCheck on root scripts - shell: bash - run: | - mapfile -t files < <(git ls-files '*.sh' | grep -v '^opencode/' || true) - - if [ "${#files[@]}" -eq 0 ]; then - echo "No repository-owned shell scripts found." - exit 0 - fi - - shellcheck --severity=warning "${files[@]}" + validate: + uses: ./.github/workflows/validate.yml + permissions: + contents: read diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index ccbee88..f51c68c 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,42 +1,38 @@ name: Docker Publish on: - workflow_run: - workflows: - - CI - types: - - completed push: + branches: + - main tags: - "v*" workflow_dispatch: -permissions: - contents: read - packages: write +permissions: {} concurrency: - group: docker-publish-${{ github.event.workflow_run.head_branch || github.ref }} + group: docker-publish-${{ github.ref }} cancel-in-progress: true jobs: + validate: + uses: ./.github/workflows/validate.yml + permissions: + contents: read + docker: - if: | - github.event_name == 'workflow_dispatch' || - startsWith(github.ref, 'refs/tags/v') || - ( - github.event_name == 'workflow_run' && - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.event == 'push' && - github.event.workflow_run.head_branch == 'main' - ) + needs: validate + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest + permissions: + contents: read + packages: write steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: - ref: ${{ github.event.workflow_run.head_sha || github.sha }} + persist-credentials: false submodules: recursive - name: Set up QEMU @@ -59,9 +55,8 @@ jobs: images: ghcr.io/${{ github.repository }} tags: | type=ref,event=tag - type=ref,event=branch,enable=${{ github.event_name == 'workflow_dispatch' }} - type=raw,value=main,enable=${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch == 'main' || github.event_name == 'workflow_dispatch' && github.ref_name == 'main' }} - type=raw,value=latest,enable=${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch == 'main' || github.event_name == 'workflow_dispatch' && github.ref_name == 'main' }} + type=ref,event=branch + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push image uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 @@ -71,9 +66,7 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max build-args: | VERSION=${{ steps.meta.outputs.version }} - REVISION=${{ github.event.workflow_run.head_sha || github.sha }} + REVISION=${{ github.sha }} SOURCE_URL=https://github.com/${{ github.repository }} diff --git a/.github/workflows/update-opencode-release.yml b/.github/workflows/update-opencode-release.yml index 0de2b40..d757649 100644 --- a/.github/workflows/update-opencode-release.yml +++ b/.github/workflows/update-opencode-release.yml @@ -11,8 +11,7 @@ on: - cron: "17 0 * * *" permissions: - contents: write - pull-requests: write + contents: read concurrency: group: update-opencode-release @@ -27,6 +26,7 @@ jobs: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: + persist-credentials: false fetch-depth: 0 submodules: recursive @@ -36,13 +36,21 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} INPUT_RELEASE_TAG: ${{ inputs.release_tag }} run: | + validate_release_tag() { + if ! printf '%s\n' "$1" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)*(-[0-9A-Za-z][0-9A-Za-z.-]*)?$'; then + printf 'Invalid release tag: %s\n' "$1" >&2 + exit 1 + fi + } + if [ -n "$INPUT_RELEASE_TAG" ]; then tag="$INPUT_RELEASE_TAG" else tag="$(gh release view --repo anomalyco/opencode --json tagName --jq .tagName)" fi - echo "tag=$tag" >> "$GITHUB_OUTPUT" + validate_release_tag "$tag" + printf 'tag=%s\n' "$tag" >> "$GITHUB_OUTPUT" - name: Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..df035c6 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,117 @@ +name: Validate + +on: + workflow_call: + +permissions: + contents: read + +jobs: + runtime-config-regression: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + submodules: recursive + + - name: Build Docker image for regression checks + run: docker build -t opencode-web-docker . + + - name: Setup Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Run runtime-config regression checks + run: bun run test:runtime-config + + build-compat-tests: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + submodules: recursive + + - name: Setup Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Run build-compat unit tests + run: bun test + + - name: Run upstream compatibility check + run: bun run test:compat + + - name: Run TypeScript typecheck + run: bun run typecheck + + - name: Run Biome lint + run: bun run lint + + - name: Check formatting + run: bun run format:check + + actionlint: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - name: Run actionlint + uses: rhysd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca # v1.7.12 + + zizmor: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 + with: + advanced-security: false + inputs: .github/workflows + min-severity: medium + min-confidence: medium + version: v1.24.1 + + shellcheck: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - name: Install ShellCheck + run: sudo apt-get update && sudo apt-get install -y shellcheck + + - name: Run ShellCheck on root scripts + shell: bash + run: | + mapfile -t files < <(git ls-files '*.sh' | grep -v '^opencode/' || true) + + if [ "${#files[@]}" -eq 0 ]; then + echo "No repository-owned shell scripts found." + exit 0 + fi + + shellcheck --severity=warning "${files[@]}"