209 lines
6.9 KiB
YAML
209 lines
6.9 KiB
YAML
name: ci
|
|
|
|
on:
|
|
push:
|
|
branches: [ main ]
|
|
tags: [ 'v*' ]
|
|
pull_request:
|
|
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
services:
|
|
mariadb:
|
|
image: mariadb:11
|
|
env:
|
|
MARIADB_DATABASE: gitea_codex
|
|
MARIADB_USER: gitea_codex
|
|
MARIADB_PASSWORD: gitea_codex
|
|
MARIADB_ROOT_PASSWORD: rootpass
|
|
ports:
|
|
- 3306:3306
|
|
options: >-
|
|
--health-cmd "mariadb-admin ping -h 127.0.0.1 -uroot -prootpass"
|
|
--health-interval 5s
|
|
--health-timeout 5s
|
|
--health-retries 20
|
|
|
|
env:
|
|
GITEA_BASE_URL: https://gitea.reversed.dev
|
|
GITEA_TOKEN: test
|
|
GITEA_BOT_USERNAME: codex-bot
|
|
GITEA_WEBHOOK_SECRET: testsecret
|
|
OPENAI_API_KEY: test-openai
|
|
ALLOWED_REPOS: org/repo
|
|
COOLDOWN_SECONDS: 60
|
|
WEBHOOK_MODE: repo
|
|
DB_HOST: mariadb
|
|
DB_PORT: 3306
|
|
DB_NAME: gitea_codex
|
|
DB_USER: gitea_codex
|
|
DB_PASSWORD: gitea_codex
|
|
TEST_DATABASE_URL: mysql+pymysql://gitea_codex:gitea_codex@mariadb:3306/gitea_codex?charset=utf8mb4
|
|
WORKDIR: /tmp/work
|
|
MAX_DIFF_BYTES: 200000
|
|
MAX_REVIEW_MINUTES: 10
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.12'
|
|
- name: Install deps
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -e .[dev]
|
|
- name: Wait for MariaDB
|
|
run: |
|
|
python - <<'PY'
|
|
import os
|
|
import time
|
|
import pymysql
|
|
|
|
host = os.environ["DB_HOST"]
|
|
port = int(os.environ["DB_PORT"])
|
|
user = os.environ["DB_USER"]
|
|
password = os.environ["DB_PASSWORD"]
|
|
database = os.environ["DB_NAME"]
|
|
|
|
for _ in range(60):
|
|
try:
|
|
conn = pymysql.connect(
|
|
host=host,
|
|
port=port,
|
|
user=user,
|
|
password=password,
|
|
database=database,
|
|
connect_timeout=2,
|
|
read_timeout=2,
|
|
write_timeout=2,
|
|
)
|
|
conn.close()
|
|
print("MariaDB is ready")
|
|
raise SystemExit(0)
|
|
except Exception as exc:
|
|
print(f"Waiting for MariaDB: {exc}")
|
|
time.sleep(2)
|
|
|
|
print("MariaDB did not become ready in time")
|
|
raise SystemExit(1)
|
|
PY
|
|
- name: Run Alembic migrations
|
|
run: alembic upgrade head
|
|
- name: Run tests
|
|
run: pytest
|
|
|
|
publish:
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
if: gitea.event_name == 'push'
|
|
env:
|
|
REGISTRY: gitea.reversed.dev
|
|
IMAGE_NAME: space/gitea-codex
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: docker/setup-buildx-action@v3
|
|
- name: Derive package metadata
|
|
id: meta
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
owner="${IMAGE_NAME%%/*}"
|
|
repo="${IMAGE_NAME##*/}"
|
|
if [ -z "${owner}" ] || [ -z "${repo}" ]; then
|
|
echo "::error::Failed to derive owner/repo from IMAGE_NAME=${IMAGE_NAME}"
|
|
exit 1
|
|
fi
|
|
echo "owner=${owner}" >> "${GITHUB_OUTPUT}"
|
|
echo "repo=${repo}" >> "${GITHUB_OUTPUT}"
|
|
- name: Login to Gitea container registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
- name: Build and push tags
|
|
shell: bash
|
|
env:
|
|
CI_SHA: ${{ gitea.sha }}
|
|
CI_REF_NAME: ${{ gitea.ref_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
|
SHA_TAG="sha-${CI_SHA::12}"
|
|
REF_TAG="${CI_REF_NAME}"
|
|
docker buildx build --push \
|
|
-t "${IMAGE}:${SHA_TAG}" \
|
|
-t "${IMAGE}:${REF_TAG}" \
|
|
.
|
|
if [ "${CI_REF_NAME}" = "main" ]; then
|
|
docker buildx build --push -t "${IMAGE}:latest" .
|
|
fi
|
|
- name: Publish image summary
|
|
shell: bash
|
|
env:
|
|
CI_SHA: ${{ gitea.sha }}
|
|
CI_REF_NAME: ${{ gitea.ref_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
|
echo "Published image tags:" >> "${GITHUB_STEP_SUMMARY}"
|
|
echo "- ${IMAGE}:${CI_REF_NAME}" >> "${GITHUB_STEP_SUMMARY}"
|
|
echo "- ${IMAGE}:sha-${CI_SHA::12}" >> "${GITHUB_STEP_SUMMARY}"
|
|
if [ "${CI_REF_NAME}" = "main" ]; then
|
|
echo "- ${IMAGE}:latest" >> "${GITHUB_STEP_SUMMARY}"
|
|
fi
|
|
- name: Link package to repository
|
|
shell: bash
|
|
env:
|
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
|
PACKAGE_OWNER: ${{ steps.meta.outputs.owner }}
|
|
PACKAGE_NAME: ${{ steps.meta.outputs.repo }}
|
|
REPO_NAME: ${{ steps.meta.outputs.repo }}
|
|
run: |
|
|
set -euo pipefail
|
|
token="${REGISTRY_PASSWORD:-${REGISTRY_TOKEN:-}}"
|
|
if [ -z "$token" ]; then
|
|
echo "::error::Registry token/password is empty. Set REGISTRY_PASSWORD or REGISTRY_TOKEN."
|
|
exit 1
|
|
fi
|
|
python3 - <<'PY'
|
|
import json
|
|
import os
|
|
import sys
|
|
import urllib.error
|
|
import urllib.parse
|
|
import urllib.request
|
|
|
|
owner = os.environ["PACKAGE_OWNER"]
|
|
package = os.environ["PACKAGE_NAME"]
|
|
repo = os.environ["REPO_NAME"]
|
|
token = os.environ["REGISTRY_PASSWORD"] or os.environ["REGISTRY_TOKEN"]
|
|
base = "https://gitea.reversed.dev/api/v1"
|
|
headers = {
|
|
"Authorization": f"token {token}",
|
|
"Accept": "application/json",
|
|
}
|
|
|
|
latest_url = f"{base}/packages/{urllib.parse.quote(owner)}/container/{urllib.parse.quote(package)}/-/latest"
|
|
req = urllib.request.Request(latest_url, headers=headers)
|
|
with urllib.request.urlopen(req) as resp:
|
|
current = json.load(resp)
|
|
|
|
linked_repo = (current.get("repository") or {}).get("name")
|
|
if linked_repo == repo:
|
|
print(f"package already linked to {owner}/{repo}")
|
|
sys.exit(0)
|
|
|
|
link_url = f"{base}/packages/{urllib.parse.quote(owner)}/container/{urllib.parse.quote(package)}/-/link/{urllib.parse.quote(repo)}"
|
|
link_req = urllib.request.Request(link_url, data=b"", method="POST", headers=headers)
|
|
try:
|
|
with urllib.request.urlopen(link_req) as resp:
|
|
print(f"linked package to {owner}/{repo}, status={resp.status}")
|
|
except urllib.error.HTTPError as exc:
|
|
body = exc.read().decode(errors="replace")
|
|
print(f"link failed: status={exc.code} body={body}")
|
|
raise
|
|
PY
|