Skip to content

Commit 2ac634f

Browse files
committed
feat: work configuration and CI
1 parent 84bcb4f commit 2ac634f

13 files changed

Lines changed: 2963 additions & 1376 deletions

.github/release.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# configure github generated release notes
2+
# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes
3+
# uses labels that can be affected implicitly based on PR titles, see workflow/conventional-label.yaml
4+
5+
changelog:
6+
exclude:
7+
labels:
8+
- ignore-for-release
9+
authors:
10+
- octocat
11+
categories:
12+
- title: Breaking Changes 🛠
13+
labels:
14+
- breaking
15+
- title: New Features 🎉
16+
labels:
17+
- feature
18+
- title: Fixes 🔧
19+
labels:
20+
- fix
21+
- title: Other Changes
22+
labels:
23+
- "*"

.github/workflows/commits.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# run lint and type-check on every commit, full quality checks on release tags
2+
3+
name: Build simple commit
4+
5+
on:
6+
push:
7+
branches: ['*']
8+
tags-ignore: [ 'v*.*.*' ]
9+
10+
jobs:
11+
build:
12+
uses: ./.github/workflows/reuse-build.yml
13+
14+
deploy:
15+
needs: build
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Send Keel notifications to staging-koumoul.com
19+
run: |
20+
curl -s --fail --show-error -X POST https://keel.admin.staging-koumoul.com/v1/webhooks/native -u ${{ secrets.KEEL_STAGING_USER }}:${{ secrets.KEEL_STAGING_PASSWORD }} -d '{"name": "ghcr.io/${{ github.repository }}", "tag": "${{ github.ref_name }}"}'
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# automatic labelling of pull request based on conventional commit names in the PR titles
2+
# see https://github.com/marketplace/actions/conventional-release-labels
3+
4+
on:
5+
pull_request_target:
6+
types: [ opened, edited ]
7+
name: conventional-release-labels
8+
jobs:
9+
label:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: bcoe/conventional-release-labels@v1
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# for pull requests we do not build a docker image, we simply run quality checks
2+
3+
name: Check pull requests
4+
5+
on: pull_request
6+
7+
jobs:
8+
quality:
9+
uses: ./.github/workflows/reuse-quality.yml

.github/workflows/releases.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# for releases we run in sequence the qualityt checks and the build
2+
3+
name: Build release
4+
5+
on:
6+
push:
7+
tags: [ 'v*.*.*' ]
8+
9+
jobs:
10+
quality:
11+
uses: ./.github/workflows/reuse-quality.yml
12+
13+
build:
14+
needs: quality
15+
uses: ./.github/workflows/reuse-build.yml
16+
17+
deploy:
18+
needs: build
19+
runs-on: ubuntu-latest
20+
steps:
21+
- id: get_version
22+
uses: battila7/get-version-action@v2
23+
24+
- name: Send Keel notifications to koumoul.com
25+
run: |
26+
curl -s --fail --show-error -X POST https://keel.admin.koumoul.com/v1/webhooks/native -u ${{ secrets.KEEL_PROD_USER }}:${{ secrets.KEEL_PROD_PASSWORD }} -d '{"name": "ghcr.io/${{ github.repository }}", "tag": "${{ steps.get_version.outputs.major }}"}'

.github/workflows/reuse-build.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Build
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
build:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Checkout git repository
11+
uses: actions/checkout@v4
12+
13+
- name: Set up Docker Buildx
14+
uses: docker/setup-buildx-action@v3
15+
16+
- name: Login to Github container registry
17+
uses: docker/login-action@v3
18+
with:
19+
registry: ghcr.io
20+
username: ${{ github.actor }}
21+
password: ${{ secrets.GITHUB_TOKEN }}
22+
23+
- name: Prepare BUILD.json
24+
run: |
25+
echo '{"version": "${{github.ref_name}}", "repository": "${{github.server_url}}/${{github.repository}}", "commit": "${{github.sha}}", "date": "'$(date -Is)'"}' > BUILD.json
26+
cat BUILD.json
27+
28+
- name: Prepare docker tags for main image
29+
id: docker_meta_main
30+
uses: docker/metadata-action@v5
31+
with:
32+
images: ghcr.io/${{ github.repository }}
33+
tags: |
34+
type=ref,event=branch
35+
type=ref,event=pr
36+
type=semver,pattern={{version}}
37+
type=semver,pattern={{major}}.{{minor}}
38+
type=semver,pattern={{major}}
39+
40+
- name: Build and push main image
41+
id: docker_build_main
42+
uses: docker/build-push-action@v5
43+
with:
44+
context: .
45+
push: true
46+
target: main
47+
tags: ${{ steps.docker_meta_main.outputs.tags }}
48+
platforms: linux/amd64
49+
labels: ${{ steps.docker_meta_main.outputs.labels }}
50+
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/buildcache
51+
cache-to: type=registry,ref=ghcr.io/${{ github.repository }}/buildcache,mode=max
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Quality checks
2+
3+
on:
4+
workflow_call:
5+
workflow_dispatch:
6+
7+
jobs:
8+
quality:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout git repository
12+
uses: actions/checkout@v4
13+
14+
- uses: actions/setup-node@v3
15+
with:
16+
node-version: 24
17+
cache: 'npm'
18+
19+
- name: Install dependencies
20+
run: npm ci
21+
22+
- name: Lint and type-check
23+
run: npm run lint && npm run check-types
24+
25+
- name: Run tests
26+
run: npm run test

docs/architecture.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,8 @@ A single Node.js process owns the whole lifecycle: it performs the registry sync
6565
| `REGISTRY_URL` | yes || Base URL of the data-fair/registry instance. |
6666
| `REGISTRY_SECRET` | yes || Secret passed as `x-secret-key` for download endpoints. |
6767
| `DATA_DIR` | no | `/data` | Root of the persistent volume (cache + generated `config.json`). |
68-
| `PUBLIC_URL` | no || Public base URL forwarded to tileserver-gl-light. |
6968
| `PORT` | no | `8080` | Port the embedded tileserver-gl-light app binds to. |
7069
| `LOG_LEVEL` | no | `info` | Log level for the wrapper. |
71-
| `ARTEFACTS_PAGE_SIZE` | no | `100` | Page size used when listing artefacts. |
7270

7371
Additional `TILESERVER_*` passthroughs may be added later as needed. v1 keeps the surface minimal.
7472

@@ -94,13 +92,13 @@ CMD ["node", "src/index.ts"]
9492

9593
1. Parse env via a zod schema; fail fast on missing `REGISTRY_URL` / `REGISTRY_SECRET`.
9694
2. Ensure `${DATA_DIR}/cache/{tilesets,styles,fonts,sprites}` exist.
97-
3. List tilesets: `GET ${REGISTRY_URL}/api/v1/artefacts?category=tileset&format=file&size=${ARTEFACTS_PAGE_SIZE}&skip=…` until pagination is exhausted.
98-
4. List styles: `GET ${REGISTRY_URL}/api/v1/artefacts?category=style&size=…&skip=…` (npm-packaged artefacts).
95+
3. List tilesets: `GET ${REGISTRY_URL}/api/v1/artefacts?category=tileset&format=file&size=1000` (single request — we never expect more than that many).
96+
4. List styles: `GET ${REGISTRY_URL}/api/v1/artefacts?category=style&size=1000` (npm-packaged artefacts).
9997
5. For each tileset: `ensureArtefact({ artefactId: t._id, cacheDir })` → yields a local `.mbtiles` path.
10098
6. For each style: resolve the latest version via `GET /api/v1/artefacts/:id/versions/latest` (or equivalent), then `ensureArtefact({ artefactId, version, cacheDir })`. The helper extracts the tarball atomically.
10199
7. Normalize each extracted style: parse its `style.json`, rewrite `glyphs` / `sprite` / `sources` entries to point at the locally cached files (see §7), and write the normalized copy next to the original.
102100
8. Build the tileserver config in memory (see §8). Also serialize it to `${DATA_DIR}/config.json` for debuggability — tileserver-gl-light is still fed the in-memory object, the on-disk copy is purely informational.
103-
9. `require('tileserver-gl-light')` → obtain the Express app factory, instantiate it with the in-memory config (and resolved `publicUrl` / `port` options), then `app.listen(PORT)`. The wrapper stays PID 1 and handles `SIGTERM`/`SIGINT` by closing the HTTP server cleanly.
101+
9. `require('tileserver-gl-light')` → obtain the Express app factory, instantiate it with the in-memory config (and resolved `port` option), then `app.listen(PORT)`. Absolute URLs in TileJSON / style responses are derived per-request from `X-Forwarded-Host` and `X-Forwarded-Proto`, matching the data-fair multi-domain convention (cf. `@data-fair/lib-express/req-origin`). The wrapper stays PID 1 and handles `SIGTERM`/`SIGINT` by closing the HTTP server cleanly.
104102

105103
If any fetch fails, the service logs the offending artefact and exits non-zero — the container is expected to be restarted by its orchestrator, or redeployed once the registry state is fixed.
106104

0 commit comments

Comments
 (0)