Compress agent skills
This commit is contained in:
@@ -5,67 +5,39 @@ description: Guide for transferring repositories from GitHub to self-hosted Gite
|
||||
|
||||
# Gitea Transfer
|
||||
|
||||
## When To Use
|
||||
Use when moving a repository from GitHub to self-hosted Gitea, converting a Gitea mirror into the canonical source, migrating active branches/PRs, or porting GitHub Actions to Gitea Actions.
|
||||
|
||||
Use this skill when moving a repository from GitHub to self-hosted Gitea, converting a Gitea mirror into the canonical source repo, migrating active branches and pull requests, porting GitHub Actions to Gitea Actions, or designing runner job images for CI.
|
||||
## Principles
|
||||
|
||||
## Operating Principles
|
||||
- Treat Gitea as canonical only after verifying the repo is no longer a mirror and the default branch exists there.
|
||||
- Keep GitHub as a recovery/reference remote unless the user explicitly asks to remove it.
|
||||
- Prefer `tea` or the Gitea API for Gitea operations; do not use `gh` for Gitea work.
|
||||
- Never paste, log, commit, or store registration tokens, API tokens, deploy keys, or package credentials.
|
||||
- Do not merge PRs, force-push, or rewrite shared branches unless the user explicitly approves.
|
||||
- Verify each cutover step with `git`, `tea`, or API output before moving on.
|
||||
|
||||
- Treat Gitea as canonical only after confirming the repo is no longer a mirror and the default branch is pushed.
|
||||
- Keep the GitHub remote as a recovery/reference remote unless the user explicitly asks to remove it.
|
||||
- Prefer `tea` or the Gitea API for Gitea repository, pull request, Actions, and runner operations.
|
||||
- Do not use `gh` for Gitea work.
|
||||
- Do not paste, log, commit, or store registration tokens, API tokens, deploy keys, or package credentials.
|
||||
- Avoid Gitea Actions secret names beginning with `GITEA_` or `GITHUB_`; those prefixes are reserved or confusing in Gitea/GitHub-compatible runners.
|
||||
- Do not modify ignored local config files such as `bunfig.toml` unless the user explicitly requests it.
|
||||
- Do not merge pull requests unless the user explicitly approves the merge.
|
||||
- Do not force-push or rewrite shared branches unless the user explicitly approves it.
|
||||
- Verify every cutover step with API or git status output before moving on.
|
||||
|
||||
## Preflight Checks
|
||||
|
||||
Confirm local state and remotes:
|
||||
## Preflight
|
||||
|
||||
```bash
|
||||
git status --short --branch
|
||||
git remote -v
|
||||
git branch --show-current
|
||||
```
|
||||
|
||||
Confirm the Gitea CLI is authenticated and targeting the expected instance:
|
||||
|
||||
```bash
|
||||
tea login list
|
||||
tea repo ls
|
||||
tea api repos/{owner}/{repo}
|
||||
```
|
||||
|
||||
Confirm the Gitea repository exists and inspect settings:
|
||||
If Gitea sits behind a reverse proxy, ensure dot directories such as `.gitea` and `.github` are not blocked by generic hidden-file rules.
|
||||
|
||||
## Mirror To Source
|
||||
|
||||
If the Gitea repo was imported as a mirror, convert it to a normal source repo in the UI or API, then verify `mirror` is `false`:
|
||||
|
||||
```bash
|
||||
tea api repos/{owner}/{repo}
|
||||
```
|
||||
|
||||
If Gitea is behind Nginx or another reverse proxy, verify dot directories are reachable. A common Forge/Nginx rule blocks paths such as `.github`, `.gitea`, `.codex`, and `.well-known`:
|
||||
|
||||
```nginx
|
||||
location ~ /\.(?!well-known).* {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
|
||||
For Gitea, that rule can break UI/API access to workflow files and agent config paths. Update the reverse proxy deliberately rather than working around it in git.
|
||||
|
||||
## Convert Mirror To Source
|
||||
|
||||
If the Gitea repository was imported as a mirror, convert it to a normal source repository before cutover. Use the Gitea UI or API, then verify:
|
||||
|
||||
```bash
|
||||
tea api repos/{owner}/{repo}
|
||||
```
|
||||
|
||||
Check that `mirror` is `false` and the expected default branch is set.
|
||||
|
||||
Enable repository features as needed:
|
||||
Enable repository features as needed, using fields supported by the installed Gitea version:
|
||||
|
||||
```bash
|
||||
tea api --method PATCH repos/{owner}/{repo} \
|
||||
@@ -73,505 +45,67 @@ tea api --method PATCH repos/{owner}/{repo} \
|
||||
--field has_actions=true
|
||||
```
|
||||
|
||||
Use the actual supported fields for the installed Gitea version. Re-read the repository after patching.
|
||||
|
||||
## Remote Cutover
|
||||
|
||||
Keep GitHub as a named fallback remote and make Gitea `origin`:
|
||||
Keep GitHub as fallback and make Gitea `origin`:
|
||||
|
||||
```bash
|
||||
git remote rename origin github
|
||||
git remote add origin ssh://git@git.example.com:30009/{owner}/{repo}.git
|
||||
git remote -v
|
||||
```
|
||||
|
||||
If `origin` already points elsewhere, adjust non-destructively:
|
||||
|
||||
```bash
|
||||
git remote set-url origin ssh://git@git.example.com:30009/{owner}/{repo}.git
|
||||
git remote add github git@github.com:{owner-or-org}/{repo}.git
|
||||
```
|
||||
|
||||
Push the default branch first:
|
||||
|
||||
```bash
|
||||
git fetch github --prune
|
||||
git push origin {default-branch}:{default-branch}
|
||||
```
|
||||
|
||||
Verify Gitea sees the branch:
|
||||
|
||||
```bash
|
||||
tea api repos/{owner}/{repo}/branches/{default-branch}
|
||||
```
|
||||
|
||||
## Branch Migration
|
||||
If `origin` already exists, adjust non-destructively with `git remote set-url origin ...` and add `github` only if absent.
|
||||
|
||||
List active GitHub branches that need to move:
|
||||
## Branches And PRs
|
||||
|
||||
- Push only active work branches, not every stale remote branch by default.
|
||||
- For each open GitHub PR, recreate enough context in Gitea: title, body, base, head, draft/WIP state, and original GitHub PR link.
|
||||
- Verify each recreated PR is open, points at the expected branches, and has the expected conflict state.
|
||||
|
||||
```bash
|
||||
git branch -r
|
||||
```
|
||||
|
||||
Push only active work branches, not every stale remote branch by default:
|
||||
|
||||
```bash
|
||||
git push origin github/{branch-name}:refs/heads/{branch-name}
|
||||
```
|
||||
|
||||
For multiple open PR heads, script carefully from reviewed data. Avoid pushing deleted/stale branches blindly.
|
||||
|
||||
Verify pushed branches:
|
||||
|
||||
```bash
|
||||
tea api repos/{owner}/{repo}/branches
|
||||
```
|
||||
|
||||
## Pull Request Migration
|
||||
|
||||
Gitea does not automatically migrate all GitHub PR review history during a basic repo transfer. Recreate open PRs with enough context to continue work:
|
||||
|
||||
- title
|
||||
- body
|
||||
- base branch
|
||||
- head branch
|
||||
- draft/WIP state in title or body if Gitea draft support is not available
|
||||
- link back to the original GitHub PR
|
||||
|
||||
Use the Gitea API or `tea`:
|
||||
|
||||
```bash
|
||||
tea pr create \
|
||||
--repo {owner}/{repo} \
|
||||
--base {base-branch} \
|
||||
--head {head-branch} \
|
||||
--title "{title}" \
|
||||
--description "{body}"
|
||||
```
|
||||
|
||||
After creating each PR, verify it is open, conflict status is correct, and the branch is correct:
|
||||
|
||||
```bash
|
||||
tea pr create --repo {owner}/{repo} --base {base} --head {head} --title "{title}" --description "{body}"
|
||||
tea pr {index} --repo {owner}/{repo}
|
||||
```
|
||||
|
||||
If comments/reviews matter, add a short migration note to the PR body linking to the original GitHub PR rather than attempting to recreate every review event.
|
||||
## Actions Porting
|
||||
|
||||
## CI Workflow Porting
|
||||
Gitea Actions workflows live in `.gitea/workflows/`. Port incrementally: tests first, then build/deploy. Keep syntax close to GitHub Actions where Gitea supports it, validate YAML, and use small commits so failures isolate one change.
|
||||
|
||||
Gitea Actions workflows live in `.gitea/workflows/`. GitHub workflows can remain temporarily in `.github/workflows/` during transition, but do not assume they run on Gitea.
|
||||
Common changes:
|
||||
|
||||
Port workflows incrementally:
|
||||
- Replace GitHub-only secrets with neutral Gitea secrets such as `REGISTRY_USERNAME`, `REGISTRY_TOKEN`, `REVIEW_BOT_TOKEN`, and `OPENCODE_GO_TOKEN`.
|
||||
- Avoid secret names beginning with `GITEA_` or `GITHUB_`.
|
||||
- Remove GitHub Packages auth unless it is still intentionally used.
|
||||
- Use service hostnames such as `postgres`, not `127.0.0.1`, for service containers.
|
||||
- Add explicit service readiness checks.
|
||||
- Do not rely on `permissions:` for security-sensitive sandboxing; some Gitea versions ignore it.
|
||||
|
||||
- Start with tests.
|
||||
- Then add build/deploy workflows.
|
||||
- Keep workflow syntax close to GitHub Actions where Gitea supports it.
|
||||
- Validate YAML before pushing.
|
||||
- Prefer small commits so each Actions failure identifies one change.
|
||||
|
||||
Example validation:
|
||||
|
||||
```bash
|
||||
ruby -e "require 'yaml'; YAML.load_file('.gitea/workflows/tests.yml'); puts 'ok'"
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Common changes when porting:
|
||||
|
||||
- Replace GitHub-only secrets with Gitea Actions secrets.
|
||||
- Use neutral secret names such as `REGISTRY_USERNAME`, `REGISTRY_TOKEN`, `REVIEW_BOT_TOKEN`, and `OPENCODE_GO_TOKEN`.
|
||||
- Remove GitHub Packages auth if the private package dependency is removed or mirrored elsewhere.
|
||||
- Replace GitHub-hosted assumptions with Gitea runner/job container assumptions.
|
||||
- Ensure `actions/checkout` version works with the installed Gitea Actions runner.
|
||||
- Use service hostnames for service containers instead of `127.0.0.1`.
|
||||
- Add explicit service readiness checks for databases.
|
||||
- Do not rely on `permissions:` for security-sensitive sandboxing in Gitea Actions; some Gitea versions ignore it.
|
||||
|
||||
For Postgres services, use the service name as the host:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_DB: app_test
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: password
|
||||
|
||||
env:
|
||||
DB_HOST: postgres
|
||||
```
|
||||
|
||||
Add a readiness loop before running tests:
|
||||
|
||||
```bash
|
||||
until PGPASSWORD=password pg_isready -h postgres -U postgres; do
|
||||
sleep 1
|
||||
done
|
||||
```
|
||||
See [runner images](references/runner-images.md), [OpenCode PR review](references/opencode-review.md), and [deploy porting](references/deploy-porting.md) for deeper CI guidance.
|
||||
|
||||
## Package Registry Cutover
|
||||
|
||||
Identify GitHub-specific package auth before enabling Gitea CI:
|
||||
Identify GitHub-specific package auth before enabling Gitea CI: npm/Bun scopes, Composer auth, workflow-written `.npmrc`, private package tarballs in lockfiles, and deploy/package secrets.
|
||||
|
||||
- npm/Bun scopes using `npm.pkg.github.com`
|
||||
- Composer auth for GitHub-hosted private packages
|
||||
- workflow steps writing `.npmrc` or package auth
|
||||
- lockfiles referencing private GitHub package tarballs
|
||||
|
||||
Options:
|
||||
|
||||
- Remove the dependency if it can be replaced locally.
|
||||
- Mirror the package to Gitea Packages.
|
||||
- Keep GitHub Packages temporarily and configure Gitea secrets deliberately.
|
||||
|
||||
Do not leave workflows requiring secrets that no longer exist. If deploy secrets are absent during cutover, prefer a clear skip for deploy-only workflows so the default branch is not red while secrets are being configured.
|
||||
|
||||
## Runner Image Strategy
|
||||
|
||||
Prefer job containers over custom runner labels for language/runtime selection.
|
||||
|
||||
Use shared CI job images when several repositories need the same runtime stack. The current shared image family is:
|
||||
|
||||
- `git.bayliss.cloud/harry/gitea-ci-runner:php8.2`
|
||||
- `git.bayliss.cloud/harry/gitea-ci-runner:php8.3`
|
||||
- `git.bayliss.cloud/harry/gitea-ci-runner:php8.4`
|
||||
- `git.bayliss.cloud/harry/gitea-ci-runner:php8.5`
|
||||
- `git.bayliss.cloud/harry/gitea-ci-runner:latest`
|
||||
|
||||
`latest` points to PHP `8.5`. Repositories should usually hardcode the PHP tag they require instead of using `latest`, so runtime upgrades are explicit per repository.
|
||||
|
||||
Good pattern:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: git.bayliss.cloud/harry/gitea-ci-runner:php8.2
|
||||
```
|
||||
|
||||
Avoid creating labels such as `stratbase-php82` just to pick an image. Labels select eligible runners; job containers select the runtime image. This keeps the runner reusable across repositories.
|
||||
|
||||
Use an instance-level or organization-level runner with generic labels such as:
|
||||
|
||||
- `ubuntu-latest`
|
||||
- `ubuntu-24.04`
|
||||
- `ubuntu-22.04`
|
||||
|
||||
If runner labels change, the runner usually needs re-registration because `.runner` pins registration details. App UI fields called "Labels Configuration" may refer to Docker metadata, not Gitea runner labels. Verify actual labels through the API:
|
||||
|
||||
```bash
|
||||
tea api admin/actions/runners
|
||||
```
|
||||
|
||||
## Building A CI Job Image
|
||||
|
||||
Create or update a shared image when workflows need system dependencies that are expensive or brittle to install per run. Prefer a central image repository over per-application image repositories unless the runtime is truly application-specific.
|
||||
|
||||
Current shared image repository:
|
||||
|
||||
```text
|
||||
ssh://git@git.bayliss.cloud:30009/harry/gitea-ci-runner.git
|
||||
https://git.bayliss.cloud/harry/gitea-ci-runner
|
||||
```
|
||||
|
||||
Current shared PHP/Laravel CI image contents:
|
||||
|
||||
- base Gitea runner job image
|
||||
- PHP CLI for `8.2`, `8.3`, `8.4`, and `8.5`, selected with `ARG PHP_VERSION`
|
||||
- Composer 2
|
||||
- Bun
|
||||
- Node.js, `npm`, and `npx`
|
||||
- Go
|
||||
- Python 3, `pip`, and `venv`
|
||||
- `jq`
|
||||
- database and cache client tools such as `postgresql-client` and `redis-tools`
|
||||
- common PHP extensions including `rdkafka`, `redis`, `pcov`, `xdebug`, `imagick`, `imap`, `pgsql`, `mysql`, `sqlite3`, `gmp`, and `gd`
|
||||
|
||||
Do not add MongoDB to the shared image unless a repository has a real runtime or CI need for it.
|
||||
|
||||
Shared Dockerfile pattern:
|
||||
|
||||
```dockerfile
|
||||
FROM docker.gitea.com/runner-images:ubuntu-latest
|
||||
|
||||
ARG PHP_VERSION=8.5
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV BUN_INSTALL=/root/.bun
|
||||
ENV PATH="/root/.bun/bin:${PATH}"
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
golang-go \
|
||||
gnupg \
|
||||
jq \
|
||||
lsb-release \
|
||||
postgresql-client \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
redis-tools \
|
||||
software-properties-common \
|
||||
unzip \
|
||||
&& install -d -m 0755 /etc/apt/keyrings \
|
||||
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
|
||||
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
|
||||
&& add-apt-repository ppa:ondrej/php -y \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
nodejs \
|
||||
php${PHP_VERSION} \
|
||||
php${PHP_VERSION}-bcmath \
|
||||
php${PHP_VERSION}-curl \
|
||||
php${PHP_VERSION}-gd \
|
||||
php${PHP_VERSION}-imagick \
|
||||
php${PHP_VERSION}-imap \
|
||||
php${PHP_VERSION}-intl \
|
||||
php${PHP_VERSION}-mbstring \
|
||||
php${PHP_VERSION}-mysql \
|
||||
php${PHP_VERSION}-pcov \
|
||||
php${PHP_VERSION}-pgsql \
|
||||
php${PHP_VERSION}-redis \
|
||||
php${PHP_VERSION}-rdkafka \
|
||||
php${PHP_VERSION}-sqlite3 \
|
||||
php${PHP_VERSION}-xdebug \
|
||||
php${PHP_VERSION}-xml \
|
||||
php${PHP_VERSION}-zip \
|
||||
&& update-alternatives --set php /usr/bin/php${PHP_VERSION} \
|
||||
&& curl -fsSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& curl -fsSL https://bun.sh/install | bash \
|
||||
&& ln -sf /root/.bun/bin/bun /usr/local/bin/bun \
|
||||
&& ln -sf /root/.bun/bin/bunx /usr/local/bin/bunx \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN php -v \
|
||||
&& php -m \
|
||||
&& composer --version \
|
||||
&& go version \
|
||||
&& bun --version \
|
||||
&& node --version \
|
||||
&& python3 --version \
|
||||
&& pg_isready --version
|
||||
```
|
||||
|
||||
Build and push manually only when necessary:
|
||||
|
||||
```bash
|
||||
docker build --build-arg PHP_VERSION=8.2 -t git.bayliss.cloud/harry/gitea-ci-runner:php8.2 -f docker/Dockerfile .
|
||||
docker push git.bayliss.cloud/harry/gitea-ci-runner:php8.2
|
||||
```
|
||||
|
||||
Prefer the image repository workflow for normal updates. Use a matrix over the supported PHP versions and push `latest` only from PHP `8.5`:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
REGISTRY: git.bayliss.cloud
|
||||
IMAGE_NAME: harry/gitea-ci-runner
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- '8.2'
|
||||
- '8.3'
|
||||
- '8.4'
|
||||
- '8.5'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check registry credentials
|
||||
env:
|
||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
if [ -z "$REGISTRY_USERNAME" ] || [ -z "$REGISTRY_TOKEN" ]; then
|
||||
echo "Skipping image publish because REGISTRY_USERNAME or REGISTRY_TOKEN is missing."
|
||||
echo "SKIP_IMAGE_PUBLISH=true" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: Login to Gitea registry
|
||||
if: env.SKIP_IMAGE_PUBLISH != 'true'
|
||||
env:
|
||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" --username "$REGISTRY_USERNAME" --password-stdin
|
||||
|
||||
- name: Build and push version tag
|
||||
if: env.SKIP_IMAGE_PUBLISH != 'true'
|
||||
run: |
|
||||
docker build \
|
||||
--build-arg PHP_VERSION="${{ matrix.php-version }}" \
|
||||
--tag "$REGISTRY/$IMAGE_NAME:php${{ matrix.php-version }}" \
|
||||
--file docker/Dockerfile \
|
||||
.
|
||||
docker push "$REGISTRY/$IMAGE_NAME:php${{ matrix.php-version }}"
|
||||
|
||||
- name: Push latest tag
|
||||
if: env.SKIP_IMAGE_PUBLISH != 'true' && matrix.php-version == '8.5'
|
||||
run: |
|
||||
docker tag "$REGISTRY/$IMAGE_NAME:php${{ matrix.php-version }}" "$REGISTRY/$IMAGE_NAME:latest"
|
||||
docker push "$REGISTRY/$IMAGE_NAME:latest"
|
||||
```
|
||||
|
||||
If the runner host exposes the Gitea registry locally, prefer the runner-local endpoint in workflow job containers for faster pulls:
|
||||
|
||||
```yaml
|
||||
container:
|
||||
image: localhost:30008/harry/gitea-ci-runner:php8.2
|
||||
```
|
||||
|
||||
Do not include `http://` in Docker image references. Configure insecure/local registry trust at the Docker daemon level if needed.
|
||||
|
||||
## OpenCode PR Review Workflow
|
||||
|
||||
Use this pattern when adding a repo-scoped OpenCode reviewer to Gitea Actions.
|
||||
|
||||
Core behavior:
|
||||
|
||||
- Trigger only from PR comments containing `/review`.
|
||||
- Do not auto-review on PR open or synchronize events for the first version.
|
||||
- Run OpenCode read-only.
|
||||
- Post or update one aggregate PR comment instead of line comments.
|
||||
- Use the PR head checkout for repository context, but keep checkout shallow.
|
||||
- Do not expose Gitea API tokens to OpenCode.
|
||||
|
||||
Required secrets:
|
||||
|
||||
- `REVIEW_BOT_TOKEN`: Gitea token for reading the repository/PR and writing issue comments.
|
||||
- `OPENCODE_GO_TOKEN`: OpenCode Go API token.
|
||||
|
||||
Recommended token permissions for `REVIEW_BOT_TOKEN`:
|
||||
|
||||
- `read:repository`
|
||||
- `read:issue`
|
||||
- `write:issue`
|
||||
|
||||
Recommended workflow shape:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
issue_comment:
|
||||
types:
|
||||
- created
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
review:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: git.bayliss.cloud/harry/gitea-ci-runner:php8.2
|
||||
```
|
||||
|
||||
In a preparation step:
|
||||
|
||||
- Read `$GITHUB_EVENT_PATH` with `jq`.
|
||||
- Skip unless the event action is `created`.
|
||||
- Skip unless the issue is a pull request.
|
||||
- Skip unless the comment contains `/review`.
|
||||
- Fetch pull request metadata from `GET /repos/{owner}/{repo}/pulls/{number}`.
|
||||
- Fetch the diff from `GET /repos/{owner}/{repo}/pulls/{number}.diff`.
|
||||
- Export `PR_NUMBER`, `REPO`, `BASE_BRANCH`, `HEAD_BRANCH`, and `HEAD_SHA` to `$GITHUB_ENV`.
|
||||
|
||||
Checkout the PR head after preparation:
|
||||
|
||||
```yaml
|
||||
- name: Checkout PR head
|
||||
if: env.SKIP_OPENCODE_REVIEW != 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ env.HEAD_SHA }}
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
```
|
||||
|
||||
Avoid `fetch-depth: 0` unless full history is required; full-history checkout can make review runs slow on Gitea runners.
|
||||
|
||||
Generate OpenCode auth at runtime from `OPENCODE_GO_TOKEN`:
|
||||
|
||||
```bash
|
||||
mkdir -p "$HOME/.local/share/opencode"
|
||||
jq -n --arg token "$OPENCODE_GO_TOKEN" '{"opencode-go": {"type": "api", "key": $token}}' > "$HOME/.local/share/opencode/auth.json"
|
||||
```
|
||||
|
||||
Disable mutation tools and unset repository tokens before invoking OpenCode:
|
||||
|
||||
```bash
|
||||
export OPENCODE_CONFIG_CONTENT='{"tools":{"write":false,"edit":false,"bash":false},"permission":{"edit":"deny","bash":"deny"},"share":"disabled","autoupdate":false}'
|
||||
unset OPENCODE_GO_TOKEN REVIEW_BOT_TOKEN GITEA_TOKEN GITHUB_TOKEN
|
||||
|
||||
opencode run \
|
||||
--model "${REVIEW_MODEL:-opencode-go/glm-5.1}" \
|
||||
--file /tmp/opencode-pr.diff \
|
||||
--title "PR #$PR_NUMBER review" \
|
||||
"Review this pull request diff for bugs, security issues, behavior regressions, and missing tests. Use the checked-out PR head tree for repository context. Focus on actionable findings. If there are no findings, say so clearly. Do not suggest style-only changes. Output Markdown with concise sections." \
|
||||
> /tmp/opencode-review.md
|
||||
```
|
||||
|
||||
Use a stable marker in the review comment body so later `/review` runs update the same comment:
|
||||
|
||||
```text
|
||||
<!-- opencode-review -->
|
||||
```
|
||||
|
||||
Gitea Actions logs can be awkward to fetch on versions before `1.26`; if `tea actions runs logs` is unavailable or incomplete, inspect run/task state through the Gitea API.
|
||||
|
||||
## Deploy Workflow Porting
|
||||
|
||||
Deploy workflows often need secrets and remote side effects. Port them after tests pass.
|
||||
|
||||
Guard required secrets explicitly:
|
||||
|
||||
```bash
|
||||
missing=()
|
||||
|
||||
for required_var in SPARK_EMAIL SPARK_KEY TIPTAP_PRO_KEY DO_SPACES_KEY DO_SPACES_SECRET DO_SPACES_ENDPOINT DO_SPACES_REGION; do
|
||||
if [ -z "${!required_var}" ]; then
|
||||
missing+=("$required_var")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#missing[@]}" -gt 0 ]; then
|
||||
echo "Skipping deploy because required secrets are missing: ${missing[*]}"
|
||||
echo "SKIP_DEPLOY=true" >> "$GITHUB_ENV"
|
||||
fi
|
||||
```
|
||||
|
||||
Gate deploy steps:
|
||||
|
||||
```yaml
|
||||
if: env.SKIP_DEPLOY != 'true'
|
||||
```
|
||||
|
||||
This keeps the default branch green while still making the missing configuration obvious in logs. File follow-up work for the missing secrets.
|
||||
|
||||
Do not manually dispatch deploy workflows that upload assets or mutate production unless the user explicitly approves it.
|
||||
Choose deliberately: remove dependency, mirror package to Gitea Packages, or keep GitHub Packages temporarily with explicit Gitea secrets. Do not leave workflows requiring missing secrets.
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before declaring cutover complete:
|
||||
|
||||
- Gitea repo is not a mirror.
|
||||
- `origin` points to Gitea.
|
||||
- `github` remote exists for recovery/reference if desired.
|
||||
- Default branch is pushed to Gitea.
|
||||
- Active PR branches are pushed to Gitea.
|
||||
- Open PRs are recreated in Gitea.
|
||||
- Repository PRs and Actions are enabled.
|
||||
- Test workflow passes on PR.
|
||||
- Test workflow passes on default branch after merge.
|
||||
- Deploy workflow either succeeds or skips cleanly with a clear missing-secrets message.
|
||||
- Optional `/review` workflow posts or updates the aggregate OpenCode review comment.
|
||||
- Runner is online with generic labels.
|
||||
- Job containers pull the expected image.
|
||||
- Local branch is synchronized with Gitea:
|
||||
- `origin` points to Gitea; `github` remote exists if retained.
|
||||
- Default branch and active PR branches are pushed.
|
||||
- Open PRs are recreated.
|
||||
- Pull requests and Actions are enabled.
|
||||
- Test workflow passes on PR and default branch.
|
||||
- Deploy workflow succeeds or skips cleanly with a clear missing-secrets message.
|
||||
- Runner is online with generic labels and job containers pull expected images.
|
||||
- Optional `/review` workflow posts or updates the aggregate review comment.
|
||||
- Local default branch is synchronized with Gitea.
|
||||
|
||||
```bash
|
||||
git pull --rebase origin {default-branch}
|
||||
@@ -580,72 +114,6 @@ git rev-list --left-right --count origin/{default-branch}...{default-branch}
|
||||
git status --short --branch
|
||||
```
|
||||
|
||||
Expected commit comparison after sync:
|
||||
Expected commit comparison after sync: `0 0`.
|
||||
|
||||
```text
|
||||
0 0
|
||||
```
|
||||
|
||||
## Common Failure Modes
|
||||
|
||||
### Dot Paths 403 In Gitea UI
|
||||
|
||||
Cause: reverse proxy blocks dot directories.
|
||||
|
||||
Fix: adjust the proxy rule for Gitea. Do not rename workflow directories.
|
||||
|
||||
### Postgres Connection Refused
|
||||
|
||||
Cause: CI app connects to `127.0.0.1` while Postgres runs as a service container.
|
||||
|
||||
Fix: use service hostname such as `postgres` and add readiness checks.
|
||||
|
||||
### Runner Job Never Starts
|
||||
|
||||
Cause: workflow `runs-on` label does not match registered runner labels.
|
||||
|
||||
Fix: use generic labels and verify with `tea api admin/actions/runners`.
|
||||
|
||||
### Image Pull Fails
|
||||
|
||||
Cause: wrong registry hostname, missing Docker daemon trust, or private package auth issue.
|
||||
|
||||
Fix: verify image reference by pulling on the runner host, then use the same host/port in the workflow.
|
||||
|
||||
### Deploy Fails For Missing Secrets
|
||||
|
||||
Cause: Gitea Actions secrets not configured yet.
|
||||
|
||||
Fix: add a preflight skip or configure secrets. File follow-up work instead of leaving the default branch red.
|
||||
|
||||
### OpenCode Review Has No Context
|
||||
|
||||
Cause: the workflow passed only a diff to OpenCode and did not checkout the PR head tree.
|
||||
|
||||
Fix: fetch the PR diff through the Gitea API, then shallow-checkout the PR head SHA with `fetch-depth: 1` and `persist-credentials: false`.
|
||||
|
||||
### OpenCode Review Checkout Is Slow
|
||||
|
||||
Cause: `actions/checkout` fetched full history with `fetch-depth: 0`.
|
||||
|
||||
Fix: checkout the PR head SHA with `fetch-depth: 1` unless full git history is required.
|
||||
|
||||
### Branch Tracks Old GitHub Remote
|
||||
|
||||
Cause: local branch upstream still points to `github/{branch}` after remote cutover.
|
||||
|
||||
Fix only if requested or useful:
|
||||
|
||||
```bash
|
||||
git branch --set-upstream-to=origin/{branch} {branch}
|
||||
```
|
||||
|
||||
## Follow-Up Issues
|
||||
|
||||
File explicit follow-up issues for work intentionally deferred during cutover, such as:
|
||||
|
||||
- configuring deploy secrets in Gitea
|
||||
- moving remaining Composer VCS repositories from GitHub to Gitea
|
||||
- removing obsolete GitHub workflows after Gitea Actions are trusted
|
||||
- deleting or archiving the GitHub repository after a retention period
|
||||
- rotating any tokens that were exposed during setup
|
||||
See [failure modes](references/failure-modes.md) when cutover or CI fails.
|
||||
|
||||
Reference in New Issue
Block a user