chore(ci): set up Renovate dependency automation
Renovate runs as a daily Gitea Actions cron (03:00 UTC, on
self-hosted runners) and opens PRs against main for dependency
updates. Picked daily-at-3am specifically so Monday's run sits
inside Renovate's default `lockFileMaintenance.schedule` ("before
4am on Monday") and triggers the weekly lockfile refresh in passing.
The workflow only handles invocation + Gitea-platform plumbing.
Bot behaviour (groupings, labels, Conventional Commits, OSV.dev
vulnerability source) lives in /renovate.json so it can evolve
without redeploying the workflow.
Groups defined: Angular, Nx, NestJS, Prisma (incl. nestjs-prisma),
Vitest, TypeScript tooling, ESLint, SWC, Tailwind. Standalone
packages get individual PRs.
Bot identity: a dedicated `apf-portal-bot` Gitea user authenticates
with a PAT stored as the RENOVATE_TOKEN repo secret. The full
onboarding procedure (user creation, scopes, secret) is documented
in docs/development.md → "Dependency updates (Renovate)".
The roadmap entry for Renovate is removed from §8 since the section
now exists.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# Per ADR-0015 (CI/CD on Gitea Actions). Scheduled invocation of
|
||||
# Renovate Bot, which proposes dependency updates as PRs against main.
|
||||
#
|
||||
# Configuration of the *bot's behaviour* (groupings, schedules, labels,
|
||||
# auto-merge, vulnerability sources) lives in /renovate.json at the
|
||||
# repo root. This workflow only controls *when* Renovate runs and how
|
||||
# it authenticates against Gitea.
|
||||
#
|
||||
# Authentication: a Gitea Personal Access Token issued for the dedicated
|
||||
# `apf-portal-bot` user, stored as the RENOVATE_TOKEN secret. The full
|
||||
# bot-onboarding procedure lives in docs/development.md → "Dependency
|
||||
# updates (Renovate)".
|
||||
|
||||
name: Renovate
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Daily 03:00 UTC — outside working hours, no contention with PR CI.
|
||||
# Picked specifically to sit inside Renovate's default
|
||||
# `lockFileMaintenance.schedule` window of "before 4am on Monday",
|
||||
# so Monday's run also triggers the weekly lockfile refresh.
|
||||
- cron: '0 3 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
runs-on: [self-hosted, on-prem]
|
||||
steps:
|
||||
- uses: renovatebot/github-action@v40
|
||||
with:
|
||||
token: ${{ secrets.RENOVATE_TOKEN }}
|
||||
configurationFile: renovate.json
|
||||
env:
|
||||
# Tell Renovate this is Gitea, not GitHub.
|
||||
RENOVATE_PLATFORM: gitea
|
||||
# Gitea API endpoint — derived from the workflow's own server
|
||||
# URL so a Gitea → GitLab migration only requires changing
|
||||
# github.server_url at the platform level (matches the
|
||||
# CLAUDE.md rule about not hardcoding the project name /
|
||||
# forge details outside repo metadata).
|
||||
RENOVATE_ENDPOINT: ${{ github.server_url }}/api/v1/
|
||||
# Don't crawl the whole instance — only this repo.
|
||||
RENOVATE_AUTODISCOVER: 'false'
|
||||
RENOVATE_REPOSITORIES: ${{ github.repository }}
|
||||
LOG_LEVEL: info
|
||||
+1
-1
@@ -13,7 +13,7 @@ This is the entry point to all project documentation. It is maintained automatic
|
||||
|
||||
### Daily development
|
||||
|
||||
- [development.md](development.md) — repo layout, prerequisites, initial setup, daily commands, conventional commit cycle. Day-to-day reference for working on the project.
|
||||
- [development.md](development.md) — repo layout, prerequisites, initial setup, daily commands, dependency updates (Renovate), conventional commit cycle. Day-to-day reference for working on the project.
|
||||
|
||||
### Architecture
|
||||
|
||||
|
||||
+34
-4
@@ -217,7 +217,38 @@ pnpm ci:perf # production build + Lighthouse CI against the static-served
|
||||
|
||||
---
|
||||
|
||||
## 5. Conventional commit cycle
|
||||
## 5. Dependency updates (Renovate)
|
||||
|
||||
[Renovate](https://docs.renovatebot.com/) runs as a scheduled workflow ([`.gitea/workflows/renovate.yml`](../.gitea/workflows/renovate.yml)) and opens PRs against `main` for dependency updates. Daily at 03:00 UTC, plus on-demand via `workflow_dispatch`.
|
||||
|
||||
Behaviour is controlled by [`renovate.json`](../renovate.json) at the repo root: groupings (Angular, Nx, NestJS, Prisma, Vitest, TypeScript tooling, ESLint, SWC, Tailwind), Conventional-Commits-compatible commit messages (`chore(deps): …` / `fix(deps): …` for vulnerability fixes), weekly lockfile maintenance, OSV.dev as the vulnerability data source.
|
||||
|
||||
### One-time bot onboarding
|
||||
|
||||
Renovate authenticates as a dedicated bot user. Setup is manual on Gitea — done once per Gitea instance, then the workflow runs unattended.
|
||||
|
||||
1. **Create a bot user.** Site Administration → Users → Create User. Suggested name: `apf-portal-bot`. Strong password, mark as **non-admin** (least privilege).
|
||||
2. **Add the bot as a collaborator** on this repo with **Write** access (Settings → Collaborators). Without write, Renovate can't push branches.
|
||||
3. **Generate a PAT for the bot.** Sign in as the bot, then User Settings → Applications → Generate New Token. Scopes needed: read/write `repository`, read/write `issue`, read `user`. Avoid `admin`.
|
||||
4. **Store the PAT as a repo secret.** Settings → Actions → Secrets → New Secret. Name: `RENOVATE_TOKEN`. Value: the token from step 3.
|
||||
5. **Sign out and forget the token locally.** It is now only retrievable via the secret store.
|
||||
|
||||
To **rotate** the PAT: regenerate at step 3, update the secret at step 4. The schedule keeps running unattended with the new token.
|
||||
|
||||
### Triggering manually
|
||||
|
||||
Repo → Actions → "Renovate" workflow → Run workflow. Useful when you've just changed `renovate.json` and want the next pass to happen immediately rather than wait for the next 03:00 UTC tick.
|
||||
|
||||
### Reviewing Renovate PRs
|
||||
|
||||
- Each Renovate PR is gated by the same CI as a human PR — `check`, `scan`, `commits`, `perf`, `a11y`. Don't merge until all are green.
|
||||
- The "Renovate Dependency Dashboard" issue (auto-created on first run) lists every pending update grouped by status. Use it to triage which PRs to expedite.
|
||||
- For a major bump that introduces breaking changes, **don't reflexively merge**: read the changelog, then either accept the work or close the PR with a "rejected" label. Renovate respects that label and won't keep re-opening the same major.
|
||||
- **Adding or removing** a dependency belongs in a feature PR, not in Renovate's scope. Renovate only updates _versions_ of existing deps.
|
||||
|
||||
---
|
||||
|
||||
## 6. Conventional commit cycle
|
||||
|
||||
1. Branch from `main` with a short slug:
|
||||
|
||||
@@ -296,7 +327,7 @@ The template guides without enforcing — sections can be left blank when irrele
|
||||
|
||||
---
|
||||
|
||||
## 6. Where to look
|
||||
## 7. Where to look
|
||||
|
||||
| Question | Doc |
|
||||
| ------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
@@ -308,7 +339,7 @@ The template guides without enforcing — sections can be left blank when irrele
|
||||
|
||||
---
|
||||
|
||||
## 7. Sections to come — roadmap by phase
|
||||
## 8. Sections to come — roadmap by phase
|
||||
|
||||
This doc starts as a phase-1 + cross-cutting reference. As features for later phases land, the corresponding sections below are filled in directly. Each entry is mapped to the ADR / implementation work that unlocks it, so a contributor can see when each section becomes real and what triggers it.
|
||||
|
||||
@@ -326,7 +357,6 @@ When a section grows beyond a short subsection, it is extracted to its own file
|
||||
| **Component patterns library** — the in-house, spartan-style components (Angular CDK + Tailwind) as they ship, with a11y notes per component (keyboard model, ARIA, screen-reader expectations). | 5b suite | First non-placeholder component in `libs/shared/ui/`. |
|
||||
| **a11y testing workflow** — running axe-core via Playwright locally, screen-reader testing notes (NVDA / VoiceOver / TalkBack), the APF user-panel cadence and how to triage findings. | 3a | First Playwright e2e suite touching real screens ([ADR-0016](decisions/0016-accessibility-baseline-wcag-aa-targeted-aaa.md)). |
|
||||
| **Performance debugging** — running Lighthouse CI locally with full config, reading the HTML reports, using `source-map-explorer` to investigate bundle bloat, interpreting BFF p95/p99 from OTel. | 3a | Lighthouse already wired in CI ([ADR-0017](decisions/0017-performance-budgets-lighthouse-ci.md)); section grows when first real route is added to the critical-routes list. |
|
||||
| **Renovate / dep update policy** — bot setup, schedule, auto-merge rules, breaking-change handling. | 3a | Security baseline ADR (paused, awaiting RSSI input). |
|
||||
| **Debugging tips** — Angular DevTools, NestJS inspector, Prisma query log, OTel trace navigation, common gotchas. | cross | Accumulates organically as the team encounters them. |
|
||||
| **Release workflow** — tag-driven release, what `release.yml` does, version bumping, changelog generation from Conventional Commits. | 3b | On-prem infrastructure ADR + populated `release.yml`. |
|
||||
| **GitLab migration runbook** — when the org migrates Gitea → GitLab, how the workflows are ported, which level-2 sections of [ADR-0015](decisions/0015-cicd-gitea-actions.md) get superseded. | future | GitLab migration ADR (6–18 months horizon). |
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["config:recommended"],
|
||||
"dependencyDashboard": true,
|
||||
"dependencyDashboardTitle": "Renovate Dependency Dashboard",
|
||||
"labels": ["dependencies"],
|
||||
"prHourlyLimit": 4,
|
||||
"prConcurrentLimit": 10,
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true
|
||||
},
|
||||
"osvVulnerabilityAlerts": true,
|
||||
"vulnerabilityAlerts": {
|
||||
"enabled": true,
|
||||
"labels": ["security", "dependencies"]
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "Angular",
|
||||
"matchPackageNames": [
|
||||
"@angular/*",
|
||||
"@angular-devkit/*",
|
||||
"@angular-eslint/*",
|
||||
"@schematics/angular",
|
||||
"angular-eslint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"groupName": "Nx",
|
||||
"matchPackageNames": ["@nx/*", "nx"]
|
||||
},
|
||||
{
|
||||
"groupName": "NestJS",
|
||||
"matchPackageNames": ["@nestjs/*"]
|
||||
},
|
||||
{
|
||||
"groupName": "Prisma",
|
||||
"matchPackageNames": ["prisma", "@prisma/*", "nestjs-prisma"]
|
||||
},
|
||||
{
|
||||
"groupName": "Vitest",
|
||||
"matchPackageNames": ["vitest", "@vitest/*", "/^vitest-/"]
|
||||
},
|
||||
{
|
||||
"groupName": "TypeScript tooling",
|
||||
"matchPackageNames": [
|
||||
"typescript",
|
||||
"typescript-eslint",
|
||||
"@typescript-eslint/*",
|
||||
"ts-node",
|
||||
"ts-jest",
|
||||
"tslib"
|
||||
]
|
||||
},
|
||||
{
|
||||
"groupName": "ESLint",
|
||||
"matchPackageNames": ["eslint", "eslint-*", "@eslint/*"]
|
||||
},
|
||||
{
|
||||
"groupName": "SWC",
|
||||
"matchPackageNames": ["@swc/*", "@swc-node/*"]
|
||||
},
|
||||
{
|
||||
"groupName": "Tailwind CSS",
|
||||
"matchPackageNames": ["tailwindcss", "@tailwindcss/*", "postcss"]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user