forked from Qortal/q-blog
ci: unify workflow + add manual trigger
This commit is contained in:
@@ -1,53 +1,81 @@
|
||||
name: CI — lint & test (self-hosted)
|
||||
name: CI (self-hosted)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["update", "main"]
|
||||
branches:
|
||||
- "**"
|
||||
pull_request:
|
||||
branches: ["main", "update"]
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
build-test:
|
||||
build_test:
|
||||
runs-on: [self-hosted, linux, x64]
|
||||
env:
|
||||
CI: "true"
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Runner info
|
||||
- name: Print env
|
||||
run: |
|
||||
echo "PWD=$(pwd)"
|
||||
uname -a || true
|
||||
echo "Actor: $GITHUB_ACTOR"
|
||||
echo "Ref: $GITHUB_REF"
|
||||
echo "SHA: $GITHUB_SHA"
|
||||
echo "Runner labels: $RUNNER_LABELS"
|
||||
node -v || true
|
||||
npm -v || true
|
||||
|
||||
# Gitea already checks out the repo on the runner.
|
||||
# If your runner does NOT, uncomment the following (requires the action to be available):
|
||||
# - uses: actions/checkout@v4
|
||||
|
||||
- name: Ensure Node is available
|
||||
shell: bash
|
||||
# Gitea self-hosted runners usually check out the repo contents automatically.
|
||||
# Add a guard: fail early if package.json is missing (indicates checkout issue).
|
||||
- name: Ensure repo contents present
|
||||
run: |
|
||||
if ! command -v node >/dev/null; then
|
||||
echo "::error::Node not found on runner. Install Node 20.x on the self-hosted runner."
|
||||
exit 1
|
||||
fi
|
||||
echo "Node: $(node -v); npm: $(npm -v)"
|
||||
test -f package.json || { echo "::error::package.json not found - check Actions checkout"; exit 1; }
|
||||
|
||||
- name: Install dependencies (smart: ci if lockfile v3; else install)
|
||||
shell: bash
|
||||
- name: Install deps (lockfile-aware)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -f package-lock.json ] && grep -q '"lockfileVersion": 3' package-lock.json; then
|
||||
echo "Using npm ci (lockfile v3)"
|
||||
npm ci --no-audit --no-fund
|
||||
set -e
|
||||
if [ -f package-lock.json ]; then
|
||||
# Read lockfileVersion without jq
|
||||
node -e "try{console.log(require('./package-lock.json').lockfileVersion||0)}catch(e){console.log(0)}" > .lockver
|
||||
v=$(cat .lockver)
|
||||
echo "lockfileVersion=$v"
|
||||
if [ "$v" = "3" ] || [ "$v" = "2" ]; then
|
||||
echo "Using npm ci"
|
||||
npm ci
|
||||
else
|
||||
echo "Unknown/old lockfileVersion ($v) → npm install"
|
||||
npm install
|
||||
fi
|
||||
else
|
||||
echo "Using npm install (no/old lockfile)"
|
||||
npm install --no-audit --no-fund
|
||||
echo "No package-lock.json → npm install"
|
||||
npm install
|
||||
fi
|
||||
|
||||
- name: Lint (phase0 scope)
|
||||
shell: bash
|
||||
run: npm run lint:phase0
|
||||
- name: Build (optional, skip if no build script)
|
||||
run: |
|
||||
if npm run | grep -qE '^ build'; then
|
||||
npm run build
|
||||
else
|
||||
echo "No build script; skipping."
|
||||
fi
|
||||
|
||||
- name: Test (vitest run)
|
||||
shell: bash
|
||||
run: npm test -- --run
|
||||
- name: Lint (phase0 scope if available, else best-effort lint)
|
||||
run: |
|
||||
if npm run | grep -qE '^ lint:phase0'; then
|
||||
npm run lint:phase0
|
||||
elif npm run | grep -qE '^ lint'; then
|
||||
npm run lint || true
|
||||
else
|
||||
echo "No lint script; skipping."
|
||||
fi
|
||||
|
||||
- name: Tests (vitest / jest autodetect)
|
||||
run: |
|
||||
if npm run | grep -qE '^ test'; then
|
||||
# Prefer vitest if present
|
||||
if npx --yes vitest --version >/dev/null 2>&1; then
|
||||
npm run -s test --silent || npm test || true
|
||||
else
|
||||
npm test || true
|
||||
fi
|
||||
else
|
||||
echo "No test script; skipping."
|
||||
fi
|
||||
|
||||
64
docs/CI.md
64
docs/CI.md
@@ -1,52 +1,20 @@
|
||||
# CI on Gitea (Self-hosted runner)
|
||||
# CI on Gitea (self-hosted runner)
|
||||
|
||||
This repo uses a single workflow: `.gitea/workflows/ci.yml`
|
||||
- Single workflow at `.gitea/workflows/ci.yml`.
|
||||
- Triggers: `push`, `pull_request`, and `workflow_dispatch` (manual button).
|
||||
- Runner labels required: `self-hosted`, `linux`, `x64` (match your `config.yaml`).
|
||||
|
||||
## Triggers
|
||||
- `push` to `update` and `main`
|
||||
- `pull_request` targeting `main` or `update`
|
||||
## Common reasons a run doesn't start
|
||||
|
||||
## Runner labels
|
||||
The job expects a runner with labels: `self-hosted`, `linux`, `x64`.
|
||||
Example runner `config.yaml`:
|
||||
1. **No workflow in the pushed branch**
|
||||
Ensure `.gitea/workflows/ci.yml` exists in the branch you push to.
|
||||
2. **Multiple workflows / conflicting filters**
|
||||
Keep only one file. Run: `bash scripts/dev/ci-ensure-one-workflow.sh` then commit.
|
||||
3. **Runner offline or labels mismatch**
|
||||
Runner must show `self-hosted`, `linux`, `x64`. Update `runs-on` or runner labels.
|
||||
4. **Lockfile vs npm**
|
||||
If `npm ci` fails with EUSAGE, refresh your `package-lock.json` locally and commit.
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
capacity: 1
|
||||
labels:
|
||||
- self-hosted
|
||||
- linux
|
||||
- x64
|
||||
```
|
||||
|
||||
> If you use a different label (e.g., `ubuntu-latest:host`), either add the standard labels to the runner, or change `runs-on` in `ci.yml` accordingly.
|
||||
|
||||
## Lockfile / npm error EUSAGE
|
||||
|
||||
If CI fails with `npm ci` complaining about the lockfile, refresh it locally:
|
||||
|
||||
```bash
|
||||
scripts/dev/update-lock.sh
|
||||
git commit -m "build: refresh lockfile"
|
||||
git push
|
||||
```
|
||||
|
||||
The workflow auto-chooses `npm install` when the lockfile is v1/v2 or missing,
|
||||
and `npm ci` when it's lockfileVersion 3.
|
||||
|
||||
## One workflow only
|
||||
|
||||
To avoid duplicate runs, keep **only** `.gitea/workflows/ci.yml`. Remove older copies:
|
||||
|
||||
```bash
|
||||
scripts/dev/ci-cleanup.sh
|
||||
git commit -m "ci: unify to single self-hosted workflow"
|
||||
git push
|
||||
```
|
||||
|
||||
## Phase versioning
|
||||
|
||||
Use `scripts/dev/bump-version.sh <semver>` to bump versions in `package.json`:
|
||||
- Phase 0 complete → `0.0.1`
|
||||
- Phase 1 complete → `0.1.0`
|
||||
- Phase 2 complete → `0.2.0`, etc.
|
||||
## Manual trigger
|
||||
- In the repo “Actions” tab, select **CI (self-hosted)** → **Run workflow** (if enabled).
|
||||
- Or push a no‑op commit: `bash scripts/dev/force-ci-push.sh <branch>`.
|
||||
|
||||
24
scripts/dev/ci-ensure-one-workflow.sh
Executable file
24
scripts/dev/ci-ensure-one-workflow.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
WF_DIR=".gitea/workflows"
|
||||
LEGACY="$WF_DIR/ci-no-marketplace.yml"
|
||||
MAIN="$WF_DIR/ci.yml"
|
||||
|
||||
echo "== Workflows before =="
|
||||
ls -1 "$WF_DIR" || true
|
||||
|
||||
if [ -f "$LEGACY" ]; then
|
||||
echo "Removing legacy workflow: $LEGACY"
|
||||
git rm -f "$LEGACY"
|
||||
fi
|
||||
|
||||
if [ ! -f "$MAIN" ]; then
|
||||
echo "::error::Missing $MAIN (place updated workflow first)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "== Workflows after =="
|
||||
ls -1 "$WF_DIR" || true
|
||||
git add "$MAIN"
|
||||
echo "Done. Commit this change to ensure only one CI workflow exists."
|
||||
11
scripts/dev/force-ci-push.sh
Executable file
11
scripts/dev/force-ci-push.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BRANCH="${1:-$(git rev-parse --abbrev-ref HEAD)}"
|
||||
msg="ci: trigger ($(date -u +'%Y-%m-%dT%H:%M:%SZ'))"
|
||||
|
||||
echo "Branch: $BRANCH"
|
||||
git add -A >/dev/null 2>&1 || true
|
||||
git commit --allow-empty -m "$msg"
|
||||
git push -u origin "$BRANCH"
|
||||
echo "Pushed. Check Actions tab for the new run."
|
||||
Reference in New Issue
Block a user