Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8a6b23d
Use local action in mention workflow
dceoy Aug 16, 2026
bba3969
Use local action in review workflow
dceoy Aug 16, 2026
3f58b6e
Test the current local action revision
dceoy Aug 16, 2026
f395581
Document reusable workflow credentials and action refs
dceoy Aug 16, 2026
24ab45e
Run review workflow directly on pull requests
dceoy Aug 16, 2026
5def935
Run mention bot directly on comments
dceoy Aug 16, 2026
d914d42
Remove redundant OpenCode wrapper workflow
dceoy Aug 16, 2026
374572f
Fix reusable workflow table formatting
dceoy Aug 16, 2026
7417e61
Use self action reference in review workflow
dceoy Aug 16, 2026
ce6a319
Use self action reference in bot workflow
dceoy Aug 16, 2026
fd2d579
Document self action references
dceoy Aug 16, 2026
34f88fe
Ignore unsupported self-reference lint
dceoy Aug 16, 2026
9d55dc9
Update reusable workflow pins after release
dceoy Aug 16, 2026
4a1a926
Tighten reusable workflow pin matching
dceoy Aug 16, 2026
ff3c2a1
Pin reusable workflow examples to self-reference implementation
dceoy Aug 16, 2026
361c07b
Update checkout pin in post-release docs refresh
dceoy Aug 16, 2026
14cbce1
Fix GNU sed option parsing in release pin updates
dceoy Aug 16, 2026
2f992f1
Fix reusable workflow pin substitution delimiter
dceoy Aug 16, 2026
ffdd407
Fix self-reference path in review workflow
dceoy Aug 16, 2026
2157cee
Fix self-reference path in bot workflow
dceoy Aug 16, 2026
de96889
Update actionlint ignore for self-reference path
dceoy Aug 16, 2026
bcd1c9c
Document valid root self-reference syntax
dceoy Aug 16, 2026
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
6 changes: 6 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
paths:
.github/workflows/opencode-*.yml:
ignore:
# actionlint does not yet recognize GitHub's $/ self repository reference.
- 'specifying action "\$/\." in invalid format because ref is missing'
31 changes: 22 additions & 9 deletions .github/workflows/opencode-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ on:
GH_TOKEN:
required: false
description: GitHub token for repository access
issue_comment:
types:
- created
pull_request_review_comment:
types:
- created
permissions:
contents: read
pull-requests: write
Expand All @@ -111,12 +117,19 @@ jobs:
(
(github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment')
&& contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
&& (
inputs.model != ''
|| startsWith(github.event.comment.body, '/oc')
|| contains(github.event.comment.body, ' /oc')
|| startsWith(github.event.comment.body, '/opencode')
|| contains(github.event.comment.body, ' /opencode')
)
) || (
github.event_name != 'issue_comment'
&& github.event_name != 'pull_request_review_comment'
&& inputs.prompt != ''
)
runs-on: ${{ inputs.runs-on }}
runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -125,7 +138,7 @@ jobs:
token: ${{ secrets.GH_TOKEN || github.token }} # zizmor: ignore[secrets-outside-env] caller-provided secret
persist-credentials: false
- name: Run OpenCode
uses: dceoy/opencode-action@v0 # zizmor: ignore[unpinned-uses] maintained by this repository's major release tag
uses: $/.
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
Expand All @@ -140,14 +153,14 @@ jobs:
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
with:
model: ${{ inputs.model }}
agent: ${{ inputs.agent }}
model: ${{ inputs.model || 'sakura/preview/Kimi-K2.7-Code' }}
agent: ${{ inputs.agent || 'build' }}
share: ${{ inputs.share }}
prompt: ${{ inputs.prompt }}
use-github-token: ${{ inputs.use-github-token }}
mentions: ${{ inputs.mentions }}
mentions: ${{ inputs.mentions || '/opencode,/oc' }}
variant: ${{ inputs.variant }}
oidc-base-url: ${{ inputs.oidc-base-url }}
opencode-version: ${{ inputs.opencode-version }}
use-bundled-toolkit: ${{ inputs.use-bundled-toolkit }}
timeout-minutes: ${{ inputs.timeout-minutes }}
oidc-base-url: ${{ inputs.oidc-base-url || 'https://api.opencode.ai' }}
opencode-version: ${{ inputs.opencode-version || 'latest' }}
use-bundled-toolkit: ${{ inputs.model == '' || inputs.use-bundled-toolkit }}
timeout-minutes: ${{ inputs.timeout-minutes || 60 }}
36 changes: 25 additions & 11 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ on:
GH_TOKEN:
required: false
description: GitHub token for repository access
pull_request:
types:
- opened
- ready_for_review
permissions:
contents: read
pull-requests: write
Expand All @@ -107,8 +111,18 @@ permissions:
actions: read
jobs:
opencode-review:
if: github.event_name == 'pull_request'
runs-on: ${{ inputs.runs-on }}
if: >
github.event_name == 'pull_request'
&& (
inputs.model != ''
|| (
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)
&& (! github.event.pull_request.draft)
&& (! startsWith(github.head_ref, 'dependabot/'))
&& (! startsWith(github.head_ref, 'renovate/'))
)
)
runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -117,7 +131,7 @@ jobs:
token: ${{ secrets.GH_TOKEN || github.token }} # zizmor: ignore[secrets-outside-env] caller-provided secret
persist-credentials: false
- name: Run OpenCode
uses: dceoy/opencode-action@v0 # zizmor: ignore[unpinned-uses] maintained by this repository's major release tag
uses: $/.
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
Expand All @@ -132,14 +146,14 @@ jobs:
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
with:
model: ${{ inputs.model }}
agent: ${{ inputs.agent }}
model: ${{ inputs.model || 'sakura/preview/Kimi-K2.7-Code' }}
agent: ${{ inputs.agent || 'build' }}
share: ${{ inputs.share }}
prompt: ${{ inputs.prompt }}
prompt: ${{ inputs.prompt || '/review-pr' }}
use-github-token: ${{ inputs.use-github-token }}
mentions: ${{ inputs.mentions }}
mentions: ${{ inputs.mentions || '/opencode,/oc' }}
variant: ${{ inputs.variant }}
oidc-base-url: ${{ inputs.oidc-base-url }}
opencode-version: ${{ inputs.opencode-version }}
use-bundled-toolkit: ${{ inputs.use-bundled-toolkit }}
timeout-minutes: ${{ inputs.timeout-minutes }}
oidc-base-url: ${{ inputs.oidc-base-url || 'https://api.opencode.ai' }}
opencode-version: ${{ inputs.opencode-version || 'latest' }}
use-bundled-toolkit: ${{ inputs.model == '' || inputs.use-bundled-toolkit }}
timeout-minutes: ${{ inputs.timeout-minutes || 60 }}
77 changes: 0 additions & 77 deletions .github/workflows/opencode.yml

This file was deleted.

54 changes: 42 additions & 12 deletions .github/workflows/post-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
permissions:
contents: write
uses: dceoy/gha-for-devops/.github/workflows/github-major-version-tag.yml@main # zizmor: ignore[unpinned-uses]
readme:
release-pins:
permissions:
contents: write
pull-requests: write
Expand Down Expand Up @@ -44,25 +44,55 @@ jobs:
fi
fi
tee -a "${GITHUB_OUTPUT}" <<< "tag=${tag}"
- name: Update README
- name: Set actions/checkout release
id: checkout
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
tag="$(gh release view --repo actions/checkout --json tagName --jq '.tagName')"
sha="$(gh api "repos/actions/checkout/commits/${tag}" --jq '.sha')"
if [[ -z "${tag}" || ! "${sha}" =~ ^[0-9a-f]{40}$ ]]; then
echo 'Failed to resolve the latest actions/checkout release commit.' >&2
exit 1
fi
tee -a "${GITHUB_OUTPUT}" <<< "tag=${tag}"
tee -a "${GITHUB_OUTPUT}" <<< "sha=${sha}"
- name: Update release pins
env:
RELEASE_TAG: ${{ steps.release.outputs.tag }}
CHECKOUT_TAG: ${{ steps.checkout.outputs.tag }}
CHECKOUT_SHA: ${{ steps.checkout.outputs.sha }}
run: |
match_count="$(grep -Ec 'uses: dceoy/opencode-action@[0-9a-f]{40}' README.md || true)"
if [[ "${match_count}" != 1 ]]; then
echo "Expected exactly one pinned dceoy/opencode-action reference in README.md, found ${match_count}." >&2
release_sha="$(git rev-parse "${RELEASE_TAG}^{commit}")"

readme_action_match_count="$(grep -Ec 'uses: dceoy/opencode-action@[0-9a-f]{40}' README.md || true)"
if [[ "${readme_action_match_count}" != 1 ]]; then
echo "Expected exactly one pinned dceoy/opencode-action reference in README.md, found ${readme_action_match_count}." >&2
exit 1
fi

readme_checkout_match_count="$(grep -Ec 'uses: actions/checkout@[0-9a-f]{40}' README.md || true)"
if [[ "${readme_checkout_match_count}" != 1 ]]; then
echo "Expected exactly one pinned actions/checkout reference in README.md, found ${readme_checkout_match_count}." >&2
exit 1
fi

workflow_match_count="$(grep -Ec 'uses: dceoy/opencode-action/\.github/workflows/opencode-(bot|review)\.yml@[0-9a-f]{40}' docs/reusable-workflows.md || true)"
if [[ "${workflow_match_count}" != 2 ]]; then
echo "Expected exactly two pinned reusable workflow references in docs/reusable-workflows.md, found ${workflow_match_count}." >&2
exit 1
else
release_sha="$(git rev-parse "${RELEASE_TAG}^{commit}")"
sed -iE "s|(uses: dceoy/opencode-action@)[0-9a-f]{40}( +#.*)?|\1${release_sha} # ${RELEASE_TAG}|" README.md
fi

sed -E -i "s|(uses: dceoy/opencode-action@)[0-9a-f]{40}( +#.*)?|\1${release_sha} # ${RELEASE_TAG}|" README.md
sed -E -i "s|(uses: actions/checkout@)[0-9a-f]{40}( +#.*)?|\1${CHECKOUT_SHA} # ${CHECKOUT_TAG}|" README.md
sed -E -i "s#(uses: dceoy/opencode-action/\.github/workflows/opencode-(bot|review)\.yml@)[0-9a-f]{40}#\1${release_sha}#g" docs/reusable-workflows.md
- name: Create pull request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} # zizmor: ignore[secrets-outside-env] caller-provided secret
commit-message: Update README for ${{ steps.release.outputs.tag }}
title: Update README for ${{ steps.release.outputs.tag }}
branch: github-actions/readme
commit-message: Update release pins for ${{ steps.release.outputs.tag }}
title: Update release pins for ${{ steps.release.outputs.tag }}
branch: github-actions/release-pins
base: ${{ github.event.repository.default_branch }}
body: Update the README action pin for ${{ steps.release.outputs.tag }}.
body: Update the README action and actions/checkout pins plus reusable workflow documentation pins for ${{ steps.release.outputs.tag }}.
delete-branch: true
14 changes: 8 additions & 6 deletions docs/reusable-workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

`opencode-action` publishes two reusable GitHub Actions workflows under `.github/workflows`. Call them as jobs with `uses`, then pass action configuration through `with` and provider credentials through `secrets`.

The examples below pin the reusable workflow definition to the commit that introduced these workflows. The called workflow currently invokes `dceoy/opencode-action@v0` internally, so this fixes the workflow definition without making the nested action reference immutable.
The examples below pin the reusable workflow definition to a full commit SHA. Inside the called workflow, `uses: $/.` references the action at the repository root from the same repository and running commit, so the workflow reference also pins the action implementation without a second checkout or a separate action revision input.

## Mention bot

Expand All @@ -25,7 +25,7 @@ jobs:
pull-requests: write
id-token: write
actions: read
uses: dceoy/opencode-action/.github/workflows/opencode-bot.yml@7c392aad14ab1281630ae0c93e81d727f76b3e92
uses: dceoy/opencode-action/.github/workflows/opencode-bot.yml@de968892b27dd42727fa175cd00610a54d091bf9
with:
model: opencode-go/kimi-k3
secrets:
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
pull-requests: write
id-token: write
actions: read
uses: dceoy/opencode-action/.github/workflows/opencode-review.yml@7c392aad14ab1281630ae0c93e81d727f76b3e92
uses: dceoy/opencode-action/.github/workflows/opencode-review.yml@de968892b27dd42727fa175cd00610a54d091bf9
with:
model: openrouter/openrouter/free
secrets:
Expand Down Expand Up @@ -83,14 +83,16 @@ Both reusable workflows expose the action configuration plus a runner input:
| `timeout-minutes` | `60` | Maximum OpenCode runtime in minutes. |
| `runs-on` | `ubuntu-latest` | Runner label for the called job. |

GitHub.com's `$/path` self repository syntax resolves to the repository and commit of the workflow where it appears, including when that workflow is called from another repository. These workflows use `$/.` because the action is defined at the repository root. GitHub Enterprise Server does not support this syntax.

## Secrets

Pass only the provider secret needed by the selected model. The reusable workflows accept `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `OPENCODE_API_KEY`, and `SAKURA_AI_ENGINE_API_KEY`.
Pass only the provider secret needed by the selected model. The reusable workflows accept `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `OPENCODE_API_KEY`, `SAKURA_AI_ENGINE_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, `DEEPSEEK_API_KEY`, `XAI_API_KEY`, `GROQ_API_KEY`, `CEREBRAS_API_KEY`, and `MOONSHOT_API_KEY`.

`GH_TOKEN` is optional. When omitted, the reusable workflow falls back to the caller's `github.token`. If `use-github-token: true`, ensure the caller grants the permissions required by the requested operation.
`GH_TOKEN` is optional. When omitted, the reusable workflow falls back to the caller's `github.token`. With `use-github-token: true`, that fallback is limited to `contents: read` by the called workflow even if the caller grants `contents: write`. For code-writing operations such as `/oc fix this`, pass a separately write-scoped `GH_TOKEN`; otherwise GitHub API writes to repository contents fail with `403`.

## Permissions

The reusable workflows request `contents: read`, `pull-requests: write`, `issues: write`, `id-token: write`, and `actions: read`. A called workflow cannot elevate the `GITHUB_TOKEN` permissions granted by its caller, so the calling job must grant the permissions needed by the selected mode.
The reusable workflows request `contents: read`, `pull-requests: write`, `issues: write`, `id-token: write`, and `actions: read`. A called workflow can only maintain or reduce the caller's `GITHUB_TOKEN` permissions: the caller must grant the requested permissions, but its higher `contents` permission cannot override the called workflow's `contents: read` ceiling. A separately supplied `GH_TOKEN` is not governed by that `GITHUB_TOKEN` permission ceiling.

The examples keep `permissions`, `with`, and `secrets` under the calling job so their scopes are explicit: `permissions` controls the caller token, `with` configures the reusable workflow inputs, and `secrets` passes credentials.
Loading