diff --git a/.github/workflows/pr-demo-bundle.yml b/.github/workflows/pr-demo-bundle.yml new file mode 100644 index 0000000..c8a1739 --- /dev/null +++ b/.github/workflows/pr-demo-bundle.yml @@ -0,0 +1,96 @@ +name: PR demo bundle + +# Builds the golf tiles from the small committed fixture on every push to any +# pull request (drafts included) and uploads a demo bundle artifact: the fresh +# golfTiles.pmtiles + the PR branch's style + a local viewer page. Download it +# from the PR page (Checks -> PR demo bundle -> Artifacts), unzip, and follow +# README.txt to test the PR in your own browser. + +on: + pull_request: + +# Cancel superseded runs for the same PR. +concurrency: + group: pr-demo-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + build-demo: + runs-on: ubuntu-latest + timeout-minutes: 45 # first uncached tilemaker compile is the long pole + permissions: + contents: read # no write tokens or secrets: safe for fork PRs + steps: + - name: Checkout (tilemaker submodule needed for the image build) + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # Same GHA build cache as docker-publish.yml, so the expensive tilemaker + # compile layer is shared. Schema/style-only PRs never recompile it: those + # files are copied after the compile layer and shadowed by the bind mount. + - name: Build golftiles image + uses: docker/build-push-action@v6 + with: + context: . + push: false + load: true + tags: golftiles:pr + build-args: JOBS=4 + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Validate style JSON parses + run: python3 -m json.tool styles/golfTilesStyle.json > /dev/null + + - name: Stage fixture into data/ + run: cp tests/fixtures/golf-fixture.osm.pbf data/ + + # Bind-mount the workspace over /app: run_all.sh reads data/*.pbf and + # writes golfTiles.pmtiles to the workspace root, and the PR's + # run_all.sh / process.lua / config.json are used as-is. + - name: Build tiles from fixture + run: docker run --rm -v "$PWD:/app" golftiles:pr + + - name: Validate pmtiles output + run: | + python3 - <<'EOF' + import struct + h = open('golfTiles.pmtiles', 'rb').read(127) + assert len(h) == 127, 'file shorter than a PMTiles header' + assert h[:7] == b'PMTiles', 'bad magic bytes' + assert h[7] == 3, f'unexpected spec version {h[7]}' + tile_data_len = struct.unpack_from(' 0, 'tile data section is empty' + assert addressed > 0, 'zero addressed tiles' + print(f'OK: {addressed} addressed tiles, {tile_data_len} bytes of tile data') + EOF + + - name: Assemble demo bundle + run: | + mkdir -p bundle + cp golfTiles.pmtiles bundle/ + cp styles/golfTilesStyle.json bundle/ + cp demo/local-viewer.html bundle/index.html + cp demo/BUNDLE_README.txt bundle/README.txt + printf '\nBuilt from PR #%s, commit %s\n' \ + "${{ github.event.pull_request.number }}" \ + "${{ github.event.pull_request.head.sha }}" >> bundle/README.txt + + - name: Short SHA for artifact name + id: vars + env: + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: echo "sha_short=${HEAD_SHA:0:7}" >> "$GITHUB_OUTPUT" + + - name: Upload demo bundle + uses: actions/upload-artifact@v4 + with: + name: golftiles-demo-pr${{ github.event.pull_request.number }}-${{ steps.vars.outputs.sha_short }} + path: bundle/ + retention-days: 14 + if-no-files-found: error diff --git a/.gitignore b/.gitignore index 3ab3729..91ee8f8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ *.pmtiles /.vscode *:Zone.Identifier -!/docs/samples/*.pmtiles \ No newline at end of file +!/docs/samples/*.pmtiles +!/tests/fixtures/*.pbf \ No newline at end of file diff --git a/demo/BUNDLE_README.txt b/demo/BUNDLE_README.txt new file mode 100644 index 0000000..f03ca29 --- /dev/null +++ b/demo/BUNDLE_README.txt @@ -0,0 +1,25 @@ +golfTiles PR demo bundle +======================== + +Contents + index.html - local map viewer (opens over Emmaboda GK, zoom 14) + golfTilesStyle.json - the style exactly as committed on this PR branch + golfTiles.pmtiles - tiles built by CI from a small test fixture + (Emmaboda GK + Nybro golfklubb area only) + +How to view + 1. Unzip this bundle into a folder. + 2. From that folder run: npx http-server -p 8080 . + 3. Open: http://localhost:8080/ + +http-server supports HTTP Range Requests, which the pmtiles library +requires. Do NOT use "python -m http.server" - it does not support +Range requests and the map will stay blank. + +You can also inspect golfTiles.pmtiles directly with the file picker +at https://pmtiles.io/ (no server needed). + +Where this came from + Built by the "PR demo bundle" GitHub Actions workflow. Find it on the + PR page under Checks -> PR demo bundle -> Artifacts (you must be + logged in to GitHub to download artifacts). diff --git a/demo/local-viewer.html b/demo/local-viewer.html new file mode 100644 index 0000000..2c03496 --- /dev/null +++ b/demo/local-viewer.html @@ -0,0 +1,44 @@ + + + + + golfTiles PR demo + + + + + + + + + +
+ + + diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 24bc95c..29f70b5 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -9,6 +9,26 @@ If you are using LLM´s tools for development/issue-tracking/discussions, please +# Testing a pull request in your browser: the PR demo bundle +Every pull request (drafts included) automatically gets a downloadable **demo bundle** built by the "PR demo bundle" GitHub Actions workflow on each push. It lets you test a PR's schema ([custom-tilemaker/process.lua](../custom-tilemaker/process.lua)) and style ([styles/golfTilesStyle.json](../styles/golfTilesStyle.json)) changes in your own browser without installing osmium-tool or tilemaker. + +The bundle contains: +- ```golfTiles.pmtiles``` — tiles freshly built by CI from a small committed test fixture ([tests/fixtures/golf-fixture.osm.pbf](../tests/fixtures/golf-fixture.osm.pbf), the area around Emmaboda GK and Nybro golfklubb). +- ```golfTilesStyle.json``` — the style exactly as committed on the PR branch. +- ```index.html``` — a local viewer that opens over Emmaboda GK at zoom 14 and points the style at the bundled tiles automatically. +- ```README.txt``` — the same instructions in short form. + +To use it: +1. On the PR page go to Checks -> **PR demo bundle** -> Artifacts and download ```golftiles-demo-pr-``` (you need to be logged in to GitHub). +2. Unzip it, and from that folder run ```npx http-server -p 8080 .``` +3. Open http://localhost:8080/ + +Note that the pmtiles library needs HTTP Range Requests, which http-server supports — ```python -m http.server``` does not, and the map will stay blank with it. You can also inspect the ```golfTiles.pmtiles``` file directly with the file picker on https://pmtiles.io/ without any server. + +The fixture is committed in the repo, so CI never downloads anything from Geofabrik; refresh the fixture manually with [tests/fixtures/extract-config.json](../tests/fixtures/extract-config.json) if it ever needs newer OSM data. The first CI run after a change to the Dockerfile or the tilemaker submodule recompiles tilemaker (~15–30 min); other runs reuse the GitHub Actions build cache and finish in a few minutes. + + + # Set up Maputnik locally in WSL to be able to work on the style: Because I have not yet uploaded the example .pmtiles or the stle to a bucket which supports CORS some acrobatics with exposing the required things locally is needed: diff --git a/tests/fixtures/extract-config.json b/tests/fixtures/extract-config.json new file mode 100644 index 0000000..d50c978 --- /dev/null +++ b/tests/fixtures/extract-config.json @@ -0,0 +1,7 @@ +{ + "directory": "tests/fixtures", + "extracts": [ + { "output": "part-emmaboda.osm.pbf", "bbox": [15.52, 56.48, 15.68, 56.58] }, + { "output": "part-nybro.osm.pbf", "bbox": [15.82, 56.70, 16.00, 56.80] } + ] +} diff --git a/tests/fixtures/golf-fixture.osm.pbf b/tests/fixtures/golf-fixture.osm.pbf new file mode 100644 index 0000000..e82f63b Binary files /dev/null and b/tests/fixtures/golf-fixture.osm.pbf differ