Skip to content

Commit bc4acd1

Browse files
authored
Merge pull request #413 from headwaymaps/mkirk/update-planet-260420
Switch to pmtiles, update planet data
2 parents b5082cd + 7d0dc66 commit bc4acd1

30 files changed

Lines changed: 215 additions & 104 deletions

bin/_headway_version.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# A bump in the DATA tag pretty much always implies a bump in the CONTAINER
2222
# tag, but not necessarily vice-versa.
2323

24-
export HEADWAY_DATA_TAG=0.10.0
24+
export HEADWAY_DATA_TAG=0.11.0
2525

2626
# # Schema change Log
2727
#

bin/build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ if [ -d "$TRANSIT_CONFIG_DIR" ]; then
4545
bin/build-transit "$CONFIG_DIR"
4646
fi
4747

48-
echo "Next, run: git co . && k8s/bin/regenerate-all"
48+
echo "Next, run: git co . && ./bin/k8s-regenerate-all"

bin/build-images

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,27 @@ function build_image() {
7777
echo "missing 'container' arg"
7878
exit 1
7979
fi
80-
local tag=$3
81-
if [ -z "$tag" ]; then
82-
echo "missing 'tag' arg"
80+
local addresses=$3
81+
if [ -z "$addresses" ]; then
82+
echo "missing 'addresses' arg"
8383
exit 1
8484
fi
8585

86-
HEADWAY_IMAGE_REPO="${HEADWAY_IMAGE_REPO:-ghcr.io/headwaymaps}"
87-
local image_ref="${HEADWAY_IMAGE_REPO}/${container}:${tag}"
88-
8986
if [ "$PUBLISH" = true ]; then
90-
echo "Publishing ${image_ref}..."
91-
dagger -c "${build_function} | publish \"${image_ref}\""
87+
echo "Publishing ${container}: ${addresses}"
88+
dagger -c "publish-multi --container=\$(${build_function}) --addresses=${addresses}"
9289
else
93-
echo "Exporting ${image_ref} to local docker..."
94-
dagger --interactive -c "${build_function} | export-image \"${image_ref}\""
90+
# Dagger's host-image-loader can only fulfill one ExportImage per session,
91+
# so export to the first tag and use `docker tag` for the rest. This keeps
92+
# all tags pointing at the same image id locally.
93+
IFS=',' read -ra _addr_list <<< "$addresses"
94+
local primary="${_addr_list[0]}"
95+
echo "Exporting ${container} to local docker: ${primary}"
96+
dagger --interactive -c "${build_function} | export-image \"${primary}\""
97+
for extra in "${_addr_list[@]:1}"; do
98+
echo "Tagging ${extra} -> ${primary}"
99+
docker tag "$primary" "$extra"
100+
done
95101
fi
96102
}
97103

@@ -108,30 +114,49 @@ function build_image_tags() {
108114
web_branding_param="--branding=$BRANDING"
109115
fi
110116

111-
# Convert comma/space separated tags to array
112-
IFS=', ' read -ra tag_array <<< "$tags_input"
117+
HEADWAY_IMAGE_REPO="${HEADWAY_IMAGE_REPO:-ghcr.io/headwaymaps}"
113118

119+
# Convert comma/space separated tags to array, dropping empties
120+
IFS=', ' read -ra tag_array <<< "$tags_input"
121+
local tags=()
114122
for tag in "${tag_array[@]}"; do
115-
# Skip empty tags
116-
if [ -z "$tag" ]; then
117-
continue
118-
fi
119-
120-
echo "Processing tag: $tag"
121-
122-
should_build "otp-init" && build_image "otp-init-container" "opentripplanner-init" "$tag"
123-
should_build "otp" && build_image "otp-serve-container" "opentripplanner" "$tag"
124-
should_build "pelias-init" && build_image "pelias-init-container" "pelias-init" "$tag"
125-
should_build "travelmux-init" && build_image "travelmux-init-container" "travelmux-init" "$tag"
126-
should_build "travelmux" && build_image "travelmux-serve-container" "travelmux" "$tag"
127-
should_build "tileserver" && build_image "tileserver-serve-container" "tileserver" "$tag"
128-
should_build "tileserver-init" && build_image "tileserver-init-container" "tileserver-init" "$tag"
129-
should_build "valhalla-init" && build_image "valhalla-init-container" "valhalla-init" "$tag"
130-
should_build "valhalla" && build_image "valhalla-serve-container" "valhalla" "$tag"
131-
should_build "frontend" && build_image "web-serve-container ${web_branding_param}" "headway" "$tag"
132-
should_build "frontend-init" && build_image "web-init-container" "headway-init" "$tag"
133-
true
123+
[ -n "$tag" ] && tags+=("$tag")
134124
done
125+
126+
if [ ${#tags[@]} -eq 0 ]; then
127+
echo "no tags provided"
128+
exit 1
129+
fi
130+
131+
# Build comma-separated "repo/container:tag" list for one image across all tags.
132+
function addresses_for() {
133+
local container=$1
134+
local out=""
135+
for tag in "${tags[@]}"; do
136+
out+="${HEADWAY_IMAGE_REPO}/${container}:${tag},"
137+
done
138+
echo "${out%,}"
139+
}
140+
141+
function build() {
142+
local filter=$1
143+
local build_function=$2
144+
local container=$3
145+
should_build "$filter" || return 0
146+
build_image "$build_function" "$container" "$(addresses_for "$container")"
147+
}
148+
149+
build "frontend" "web-serve-container ${web_branding_param}" "headway"
150+
build "frontend-init" "web-init-container" "headway-init"
151+
build "otp-init" "otp-init-container" "opentripplanner-init"
152+
build "otp" "otp-serve-container" "opentripplanner"
153+
build "pelias-init" "pelias-init-container" "pelias-init"
154+
build "tileserver" "tileserver-serve-container" "tileserver"
155+
build "tileserver-init" "tileserver-init-container" "tileserver-init"
156+
build "travelmux-init" "travelmux-init-container" "travelmux-init"
157+
build "travelmux" "travelmux-serve-container" "travelmux"
158+
build "valhalla-init" "valhalla-init-container" "valhalla-init"
159+
build "valhalla" "valhalla-serve-container" "valhalla"
135160
}
136161

137162
echo "Mode: $([ "$PUBLISH" = true ] && echo "Publish" || echo "Export")"

bin/publish-data

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ set -o nounset
8888

8989
upload "${HEADWAY_AREA}.valhalla.tar.zst" "${HEADWAY_DATA_TAG}/${HEADWAY_AREA_TAG}"
9090
upload "${HEADWAY_AREA}.elasticsearch.tar.zst" "${HEADWAY_DATA_TAG}/${HEADWAY_AREA_TAG}"
91-
upload "${HEADWAY_AREA}.mbtiles" "${HEADWAY_DATA_TAG}/${HEADWAY_AREA_TAG}"
91+
upload "${HEADWAY_AREA}.pmtiles" "${HEADWAY_DATA_TAG}/${HEADWAY_AREA_TAG}"
9292
upload "${HEADWAY_AREA}.placeholder.tar.zst" "${HEADWAY_DATA_TAG}/${HEADWAY_AREA_TAG}"
9393
upload "${HEADWAY_AREA}.osm.pbf" "${HEADWAY_DATA_TAG}/${HEADWAY_AREA_TAG}"
9494

bin/reset-services

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
# Stop, remove volumes, and restart docker compose services
3+
4+
set -e
5+
6+
CONFIG_DIR="$1"
7+
if [ -z "$CONFIG_DIR" ]; then
8+
cat <<EOS
9+
Usage: $0 <build-config-dir>
10+
Example: Basic
11+
$0 builds/Bogota
12+
Example: With Transit
13+
COMPOSE_FILE=docker-compose-with-transit.yaml $0 builds/Seattle
14+
EOS
15+
exit 1
16+
fi
17+
18+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19+
20+
"$SCRIPT_DIR/stop-and-remove-services" "$CONFIG_DIR"
21+
"$SCRIPT_DIR/start-services" "$CONFIG_DIR"

bin/start-services

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,27 @@
33

44
set -e
55

6+
FOLLOW_LOGS=1
7+
while [ $# -gt 0 ]; do
8+
case "$1" in
9+
--no-follow-logs)
10+
FOLLOW_LOGS=0
11+
shift
12+
;;
13+
-*)
14+
echo "Unknown option: $1"
15+
exit 1
16+
;;
17+
*)
18+
break
19+
;;
20+
esac
21+
done
22+
623
CONFIG_DIR="$1"
724
if [ -z "$CONFIG_DIR" ]; then
825
cat <<EOS
9-
Usage: $0 <build-config-dir>
26+
Usage: $0 [--no-follow-logs] <build-config-dir>
1027
Example: Basic
1128
$0 builds/Bogota
1229
Example: With Transit
@@ -50,3 +67,9 @@ echo "Services started! Use bin/wait-for-services to check readiness."
5067
echo ""
5168
echo "To stop services and remove volumes, run:"
5269
echo " bin/stop-and-remove-services $CONFIG_DIR"
70+
echo ""
71+
72+
cd "$APP_ROOT"
73+
if [ "$FOLLOW_LOGS" -eq 1 ]; then
74+
bin/docker-compose "$CONFIG_DIR" logs --follow
75+
fi

bin/update-planet-version

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
APP_ROOT=$(git rev-parse --show-toplevel)
6+
ENV_FILE="$APP_ROOT/builds/planet/.env"
7+
S3_BASE="s3://osm-planet-us-west-2/planet/pbf"
8+
9+
LATEST_YEAR=$(aws s3 ls --no-sign-request "$S3_BASE/" \
10+
| grep -oE '[0-9]{4}/' \
11+
| tr -d '/' \
12+
| sort -n \
13+
| tail -1)
14+
15+
LATEST_FILE=$(aws s3 ls --no-sign-request "$S3_BASE/$LATEST_YEAR/" \
16+
| grep '\.osm\.pbf$' \
17+
| awk '{print $4}' \
18+
| sort \
19+
| tail -1)
20+
21+
YYMMDD=$(echo "$LATEST_FILE" | sed 's/planet-\([0-9]*\)\.osm\.pbf/\1/')
22+
NEW_VERSION="v1.$YYMMDD"
23+
CURRENT_VERSION=$(grep '^HEADWAY_PLANET_VERSION=' "$ENV_FILE" | cut -d= -f2)
24+
25+
if [ "$NEW_VERSION" = "$CURRENT_VERSION" ]; then
26+
echo "Already up to date: $CURRENT_VERSION"
27+
exit 0
28+
fi
29+
30+
echo "Updating HEADWAY_PLANET_VERSION: $CURRENT_VERSION -> $NEW_VERSION"
31+
32+
perl -i -pe "s/^HEADWAY_PLANET_VERSION=.*/HEADWAY_PLANET_VERSION=$NEW_VERSION/" "$ENV_FILE"

builds/planet/.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# See latest releases with: aws s3 ls --no-sign-request s3://osm-planet-us-west-2/planet/pbf/2025/
22
# And update the HEADWAY_PLANET_VERSION accordingly. The build scripts will fetch the corresponding osm.pbf
3-
HEADWAY_PLANET_VERSION=v1.251124
3+
HEADWAY_PLANET_VERSION=v1.260420
44
HEADWAY_AREA=maps-earth-planet-${HEADWAY_PLANET_VERSION}
55
HEADWAY_AREA_TAG="$HEADWAY_AREA"
66
HEADWAY_COUNTRIES="ALL"

dagger/main.go

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ func (h *Headway) Build(ctx context.Context) (*dagger.Directory, error) {
153153

154154
output = output.WithFile(h.Area+".osm.pbf", h.OSMExport.File)
155155

156-
mbtiles, err := h.Mbtiles(ctx)
156+
pmtiles, err := h.Pmtiles(ctx)
157157
if err != nil {
158-
return nil, fmt.Errorf("failed to build mbtiles: %w", err)
158+
return nil, fmt.Errorf("failed to build pmtiles: %w", err)
159159
}
160-
output = output.WithFile(h.Area+".mbtiles", mbtiles)
160+
output = output.WithFile(h.Area+".pmtiles", pmtiles)
161161

162162
valhalla := h.ValhallaTiles(ctx)
163163
output = output.WithFile(h.Area+".valhalla.tar.zst", valhalla.Compress())
@@ -217,11 +217,11 @@ func martinBinary() *dagger.File {
217217
const martinFeatures = "fonts,mbtiles,pmtiles,styles,sprites"
218218

219219
// To build from source (e.g. for debugging a fork), set this to true
220-
const buildFromSource = false
220+
const buildFromSource = true
221221
if buildFromSource {
222222
return rustContainer("git").
223223
WithEnvVariable("CACHE_BUSTER", time.Now().String()).
224-
WithExec([]string{"git", "clone", "--branch", "mkirk/fix-forwarding-header", "--depth=1", "https://github.com/michaelkirk/martin.git", "/martin"}).
224+
WithExec([]string{"git", "clone", "--branch", "mkirk/relative-source-urls", "--depth=1", "https://github.com/michaelkirk/martin.git", "/martin"}).
225225
WithWorkdir("/martin").
226226
WithExec([]string{"cargo", "build", "--release", "--locked", "--no-default-features", "--features", martinFeatures}).
227227
File("target/release/martin")
@@ -244,15 +244,15 @@ func (h *Headway) TileserverServeContainer(ctx context.Context) *dagger.Containe
244244
WithDefaultArgs([]string{"/app/configure-and-run.sh"})
245245
}
246246

247-
// Builds mbtiles using Planetiler
248-
func (h *Headway) Mbtiles(ctx context.Context) (*dagger.File, error) {
247+
// Builds maptiles using Planetiler
248+
func (h *Headway) Pmtiles(ctx context.Context) (*dagger.File, error) {
249249

250250
if h.OSMExport == nil || h.OSMExport.File == nil {
251-
panic("Headway.OSMExport.File must be set to build mbtiles")
251+
panic("Headway.OSMExport.File must be set to build pmtiles")
252252
}
253253

254254
container := dag.Container().
255-
From("ghcr.io/onthegomap/planetiler:0.7.0")
255+
From("ghcr.io/onthegomap/planetiler:0.10.2")
256256

257257
memoryScript := h.ServiceDir("tilebuilder").File("percent-of-available-memory")
258258
memoryBudget, err := container.
@@ -266,30 +266,34 @@ func (h *Headway) Mbtiles(ctx context.Context) (*dagger.File, error) {
266266
fixturesUrl := getEnvWithDefault("HEADWAY_PLANETILER_FIXTURES_URL", "https://data.maps.earth/planetiler_fixtures/sources.tar")
267267

268268
container = container.
269+
WithMountedFile("/tmp/planetile-fixture-sources.tar", downloadFile(fixturesUrl)).
269270
WithExec([]string{"mkdir", "-p", "/data/sources"}).
270-
WithExec([]string{"sh", "-c", "curl --no-progress-meter " + fixturesUrl + " | tar -x --directory /data/sources"}).
271+
WithExec([]string{"sh", "-c", "tar -x --directory /data/sources -f /tmp/planetile-fixture-sources.tar"}).
271272
WithMountedFile("/data/data.osm.pbf", h.OSMExport.File)
272273

273274
entrypoint, err := container.Entrypoint(ctx)
274275
if err != nil {
275276
return nil, fmt.Errorf("failed to get entrypoint: %w", err)
276277
}
277-
278+
output := "/data/output.pmtiles"
279+
entrypoint = append(entrypoint,
280+
"--osm_path=/data/data.osm.pbf",
281+
"--force",
282+
fmt.Sprintf("--output=%s", output),
283+
)
278284
if h.IsPlanetBuild {
279285
container = container.WithExec(append(entrypoint,
280-
"--osm_path=/data/data.osm.pbf",
281-
"--force",
282286
"--bounds=planet",
283287
"--nodemap-type=array",
284288
"--storage=mmap",
285289
fmt.Sprintf("-Xmx%d", memoryBudget),
286290
"-XX:MaxHeapFreeRatio=40",
287291
))
288292
} else {
289-
container = container.WithExec(append(entrypoint, "--osm_path=/data/data.osm.pbf", "--force"))
293+
container = container.WithExec(entrypoint)
290294
}
291295

292-
return container.File("/data/output.mbtiles"), nil
296+
return container.File(output), nil
293297
}
294298

295299
/**
@@ -564,6 +568,24 @@ func WithAptPackages(container *dagger.Container, packages ...string) *dagger.Co
564568
return container.WithExec([]string{"sh", "-c", cmd})
565569
}
566570

571+
// Publish a container to multiple registry addresses in a single Dagger
572+
// session, so every tag points at the same image digest.
573+
func (h *Headway) PublishMulti(
574+
ctx context.Context,
575+
container *dagger.Container,
576+
addresses []string,
577+
) ([]string, error) {
578+
out := make([]string, 0, len(addresses))
579+
for _, addr := range addresses {
580+
ref, err := container.Publish(ctx, addr)
581+
if err != nil {
582+
return nil, fmt.Errorf("publishing %q: %w", addr, err)
583+
}
584+
out = append(out, ref)
585+
}
586+
return out, nil
587+
}
588+
567589
func compressDir(dir *dagger.Directory) *dagger.File {
568590
container := slimContainer("zstd").
569591
WithExec([]string{"mkdir", "/app"}).

docker-compose-with-transit.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ services:
33
image: ghcr.io/headwaymaps/tileserver-init:latest
44
env_file: builds/${HEADWAY_AREA:?}/.env
55
environment:
6-
AREAMAP_ARTIFACT_SOURCE: /bootstrap/${HEADWAY_AREA}.mbtiles
7-
AREAMAP_ARTIFACT_DEST: /data/tiles/areamap.mbtiles
6+
AREAMAP_ARTIFACT_SOURCE: /bootstrap/${HEADWAY_AREA}.pmtiles
7+
AREAMAP_ARTIFACT_DEST: /data/tiles/areamap.pmtiles
88
TERRAIN_ARTIFACT_SOURCE: /bootstrap/terrain.mbtiles
99
TERRAIN_ARTIFACT_DEST: /data/tiles/terrain.mbtiles
1010
LANDCOVER_ARTIFACT_SOURCE: /bootstrap/landcover.mbtiles

0 commit comments

Comments
 (0)