diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..9defcf2 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,91 @@ +name: Release + +# Auto-tagging baserat på conventional commits sedan senaste taggen. +# feat: → minor bump (1.2.9 → 1.3.0) +# fix: → patch bump (1.2.9 → 1.2.10) +# "!:" eller "BREAKING CHANGE" → major bump (1.2.9 → 2.0.0) +# Andra prefix (chore:, docs:, ci:, refactor:, style:, test:) bumpar inte. +# Skippas tyst när inga releaseable commits hittas — t.ex. när workflow:n själv pushar version-commiten. +# Push av tag triggar deploy.yml (PACKAGES_TOKEN är en PAT så cross-workflow-triggers funkar). + +on: + push: + branches: [main] + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.PACKAGES_TOKEN }} + + - name: Configure git + run: | + git config user.name "Release Bot" + git config user.email "noreply@shcizo.se" + + - name: Determine version bump + id: bump + run: | + set -euo pipefail + + LAST_TAG=$(git describe --tags --abbrev=0 --match 'v*' 2>/dev/null || echo "") + if [ -z "$LAST_TAG" ]; then + RANGE="" + echo "No previous v* tag found — scanning all commits." + else + RANGE="${LAST_TAG}..HEAD" + echo "Scanning commits since ${LAST_TAG}." + fi + + BUMP="none" + while IFS= read -r subject; do + [ -z "$subject" ] && continue + if echo "$subject" | grep -qE "^[a-z]+(\([^)]+\))?!:|BREAKING[ -]CHANGE"; then + BUMP="major" + break + elif echo "$subject" | grep -qE "^feat(\([^)]+\))?:"; then + [ "$BUMP" != "major" ] && BUMP="minor" + elif echo "$subject" | grep -qE "^fix(\([^)]+\))?:"; then + [ "$BUMP" = "none" ] && BUMP="patch" + fi + done < <(git log ${RANGE} --no-merges --pretty=format:%s) + + echo "Determined bump: ${BUMP}" + echo "bump=${BUMP}" >> "$GITHUB_OUTPUT" + + - name: Compute new version + if: steps.bump.outputs.bump != 'none' + id: version + run: | + set -euo pipefail + CURRENT=$(node -p "require('./package.json').version") + IFS=. read -r MAJ MIN PAT <<< "$CURRENT" + case "${{ steps.bump.outputs.bump }}" in + major) NEW="$((MAJ+1)).0.0" ;; + minor) NEW="${MAJ}.$((MIN+1)).0" ;; + patch) NEW="${MAJ}.${MIN}.$((PAT+1))" ;; + esac + echo "Bumping ${CURRENT} → ${NEW}" + echo "new=${NEW}" >> "$GITHUB_OUTPUT" + + - name: Update files, commit, tag, push + if: steps.bump.outputs.bump != 'none' + run: | + set -euo pipefail + NEW="${{ steps.version.outputs.new }}" + + npm version "$NEW" --no-git-tag-version + + git add package.json package-lock.json + git commit -m "$NEW" + git tag "v${NEW}" + git push origin main "v${NEW}" + + - name: No-op summary + if: steps.bump.outputs.bump == 'none' + run: echo "No feat/fix/breaking commits since last tag — no release." diff --git a/CLAUDE.md b/CLAUDE.md index 0355ecb..34badf7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,7 +46,7 @@ public/ - **Logging:** Use `require('./logger')` (or relative path). Never use `console.log/error` in backend code. Use appropriate Pino levels: `debug` for verbose/diagnostic data, `info` for operational status, `warn` for retries/degraded state, `error` for failures, `fatal` for startup crashes. - **Frontend JS:** `console.error` is fine in `public/js/` — runs in browser, no Pino. - **Commits:** Conventional commits (`feat:`, `fix:`, `refactor:`, `chore:`, `ci:`). -- **Releases:** Manual version bump — edit `version` in `package.json` + `package-lock.json`, commit as ``, tag `v`, push commit + tag (`git push origin main v`). Triggers `.gitea/workflows/deploy.yml` which (1) builds and pushes the image to `gitea.shcizo.se/shcizo/pdga-rating:` + `:latest`, then (2) calls `package-updater-action` against `updater.shcizo.se/update` to roll out the new image. Required secrets: `PACKAGES_TOKEN` (PAT with `write:package`, for registry auth — the auto-injected `GITEA_TOKEN` does not have effective registry access) and `UPDATER_API_KEY` (for the updater endpoint). The action repo `shcizo/package-updater-action` is referenced via full Gitea URL (`https://gitea.shcizo.se/...`) since `uses:` defaults to GitHub. +- **Releases:** Automated via `.gitea/workflows/release.yml` on push to `main`. Workflow scans conventional commits sedan senaste `v*`-taggen och bumpar strikt semver: `feat:` → minor, `fix:` → patch, `!:`/`BREAKING CHANGE` → major. Andra prefix (`chore:`, `docs:`, `ci:`, `refactor:`, `style:`, `test:`) bumpar inte. Workflow:n uppdaterar `package.json` + `package-lock.json`, committar som ``, taggar `v` och pushar. Tag-pushen triggar `.gitea/workflows/deploy.yml` som (1) bygger + pushar image till `gitea.shcizo.se/shcizo/pdga-rating:` + `:latest`, sen (2) anropar `package-updater-action` mot `updater.shcizo.se/update`. Required secrets: `PACKAGES_TOKEN` (PAT med `write:package` + repo-push-scope — används av både release.yml för att pusha main/tag och deploy.yml för registry-auth; auto-injicerade `GITEA_TOKEN` triggar inte cross-workflows och saknar effective registry-access) och `UPDATER_API_KEY` (för updater-endpointen). Action-repot `shcizo/package-updater-action` refereras via full Gitea-URL (`https://gitea.shcizo.se/...`) eftersom `uses:` defaultar till GitHub. **Manuell tag** är fortfarande möjlig om release-workflow:n skippas eller behöver kringgås — pusha bara `v`-tag direkt. - **Scraping:** Two strategies per entity: direct HTTP (fast, preferred) with Puppeteer fallback (stealth plugin for anti-bot). Rate limiting must be respected. - **Database:** Migrations run automatically on startup in `db.js`. Schema changes go there. - **Templates:** EJS with shared layout in `views/partials/`. Pages use HTMX for dynamic content loading.