Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 49 additions & 18 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,58 @@ env:

jobs:
docker:
name: Build and publish Docker image
name: Build and publish Docker image (${{ matrix.variant }})
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
# Stable: default build, gets the moving `latest` tag.
- variant: stable
maven_profiles: ""
latest: "true"
# Snapshot: built against the validator core SNAPSHOT. Never `latest`.
- variant: snapshot
maven_profiles: "snapshot"
latest: "false"
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

# Derive the API version and the validator core version (honouring the
# matrix Maven profiles) straight from pom.xml so image tags can never
# drift from the actual build. Image name is lower-cased for GHCR.
- name: Compute image tags
id: tags
run: |
set -euo pipefail
PROFILE_ARG=""
if [ -n "${{ matrix.maven_profiles }}" ]; then
PROFILE_ARG="-P${{ matrix.maven_profiles }}"
fi
API_VERSION=$(mvn -q -N $PROFILE_ARG help:evaluate -Dexpression=project.version -DforceStdout)
VALIDATOR_VERSION=$(mvn -q -N $PROFILE_ARG help:evaluate -Dexpression=gtfs-validator.version -DforceStdout)
IMAGE=$(echo "${REGISTRY}/${IMAGE_NAME}" | tr '[:upper:]' '[:lower:]')
# Self-documenting tag: <apiVersion>-validator<validatorCoreVersion>.
# The `validator` infix scopes the trailing version to the validator
# core, not the API (the two versions evolve independently).
DUAL_TAG="${IMAGE}:${API_VERSION}-validator${VALIDATOR_VERSION}"
TAGS="${DUAL_TAG}"
if [ "${{ matrix.latest }}" = "true" ]; then
TAGS="${TAGS}"$'\n'"${IMAGE}:latest"
fi
{
echo "tags<<EOF"
echo "${TAGS}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
echo "Resolved tags:"
echo "${TAGS}"

- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
Expand All @@ -41,26 +84,14 @@ jobs:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
Comment thread
jcpitre marked this conversation as resolved.
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}
type=sha
- name: Build and push Docker image
uses: docker/build-push-action@v7
with:
context: .
build-args: |
MAVEN_PROFILES=${{ matrix.maven_profiles }}
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.tags.outputs.tags }}
cache-from: type=gha,scope=${{ matrix.variant }}
cache-to: type=gha,mode=max,scope=${{ matrix.variant }}
9 changes: 7 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /workspace

# Optional comma-separated Maven profiles to activate (e.g. "snapshot" to build
# against a pre-release SNAPSHOT of the GTFS validator core). Empty by default,
# which produces a stable build.
ARG MAVEN_PROFILES=""

# Cache dependencies first.
COPY pom.xml .
COPY .openapi-generator-ignore .
RUN mvn -B -q dependency:go-offline
RUN mvn -B -q ${MAVEN_PROFILES:+-P}${MAVEN_PROFILES} dependency:go-offline

# Build the application.
COPY src ./src
COPY docs ./docs
RUN mvn -B -q clean package -DskipTests
RUN mvn -B -q ${MAVEN_PROFILES:+-P}${MAVEN_PROFILES} clean package -DskipTests

# --- Runtime stage -----------------------------------------------------------
FROM eclipse-temurin:17-jre
Expand Down
46 changes: 44 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ mvn test # run the integration tests only
mvn verify # also runs the spotless code-style check
```

### Building against a validator SNAPSHOT

The default build uses the stable validator core release (`gtfs-validator.version`,
currently `8.0.1`). To build against a pre-release **SNAPSHOT** of the validator
core instead, activate the opt-in `snapshot` profile:

```bash
mvn -Psnapshot clean package # uses the pinned snapshot (8.0.2-SNAPSHOT)

# override the snapshot version explicitly:
mvn -Psnapshot -Dgtfs-validator.version=8.0.2-SNAPSHOT clean package
```

The profile enables the public [Maven Central snapshot repository][central-snapshots]
(no credentials needed) — required because Maven only resolves `-SNAPSHOT`
artifacts from repositories that explicitly enable snapshots. The API's own
version is unaffected; only the validator core dependency changes.

[central-snapshots]: https://central.sonatype.com/repository/maven-snapshots/

## Code style

Matches the [gtfs-validator](https://github.com/MobilityData/gtfs-validator) repo:
Expand Down Expand Up @@ -102,14 +122,36 @@ docker run --rm -p 8080:8080 gtfs-validator-api:1.0.0

Pass JVM options via `JAVA_OPTS`, e.g. `-e JAVA_OPTS="-Xmx4g"`.

To build an image against a validator-core SNAPSHOT, pass the `MAVEN_PROFILES`
build arg:

```bash
docker build --build-arg MAVEN_PROFILES=snapshot -t gtfs-validator-api:snapshot .
```

### Pre-built image

CI publishes multi-arch images (`linux/amd64`, `linux/arm64`) to the GitHub
Container Registry on every push to the default branch and on version tags:
Container Registry on every push to the default branch and on version tags. Two
variants are published:

| Variant | Tags | Validator core |
|---------|------|----------------|
| Stable | `latest`, `1.0.0-validator8.0.1` | stable release |
| Snapshot | `1.0.0-validator8.0.2-SNAPSHOT` | pre-release SNAPSHOT |

The tag format is `<apiVersion>-validator<validatorCoreVersion>`: the `validator`
infix scopes the trailing version to the validator **core**, not the API (the two
versions evolve independently). `latest` always points at the stable variant; the
snapshot image is never tagged `latest`.

```bash
# Stable
docker pull ghcr.io/mobilitydata/gtfs-validator-api:latest
docker run --rm -p 8080:8080 ghcr.io/mobilitydata/gtfs-validator-api:latest

# Snapshot (built against the validator core SNAPSHOT)
docker pull ghcr.io/mobilitydata/gtfs-validator-api:1.0.0-validator8.0.2-SNAPSHOT
```

## Continuous integration
Expand All @@ -119,7 +161,7 @@ GitHub Actions workflows live in `.github/workflows/`:
| Workflow | Trigger | Purpose |
|----------|---------|---------|
| `build.yml` | push / PR to `main`/`master`, manual | `mvn clean verify` — OpenAPI generation, compile, integration tests and the Spotless code-style check; uploads the built jar. |
| `docker.yml` | push / PR / tag `v*` / release, manual | Builds the Docker image (multi-arch). On non-PR events it pushes to `ghcr.io/<owner>/gtfs-validator-api` with branch, `latest`, semver and commit-SHA tags. |
| `docker.yml` | push / PR / tag `v*` / release, manual | Builds two image variants (stable and validator-SNAPSHOT) via a matrix, multi-arch. On non-PR events it pushes to `ghcr.io/<owner>/gtfs-validator-api`; stable gets `latest` + `<api>-validator<core>`, snapshot gets `<api>-validator<core>` only. PRs build both but push neither. |

## Configuration

Expand Down
35 changes: 34 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@
<jackson-databind-nullable.version>0.2.10</jackson-databind-nullable.version>
<jakarta-annotation.version>3.0.0</jakarta-annotation.version>

<!-- Validator core version is independent of this project's version. -->
<!-- Validator core version is independent of this project's version.
Default is the stable release. Build with -Psnapshot to override
this with the latest pre-release SNAPSHOT (see the snapshot profile
at the end of this file). -->
<gtfs-validator.version>8.0.1</gtfs-validator.version>

<!-- Patched versions overriding vulnerable validator transitive dependencies. -->
Expand Down Expand Up @@ -294,4 +297,34 @@
</plugin>
</plugins>
</build>

<profiles>
<!-- Opt-in profile to build against a pre-release SNAPSHOT of the GTFS
validator core instead of the stable default. Activate with:
mvn -Psnapshot ...
It overrides gtfs-validator.version and enables the Maven Central
snapshot repository (Maven only resolves *-SNAPSHOT from repos that
explicitly enable snapshots). The snapshot repo is public; no
credentials are required to consume it. Override the version on the
command line with -Dgtfs-validator.version=X.Y.Z-SNAPSHOT if needed. -->
<profile>
<id>snapshot</id>
<properties>
<gtfs-validator.version>8.0.2-SNAPSHOT</gtfs-validator.version>
</properties>
<repositories>
<repository>
<id>central-snapshots</id>
<name>Maven Central Snapshots</name>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
</project>
Loading