diff --git a/.github/actions/extract-version/action.yml b/.github/actions/extract-version/action.yml new file mode 100644 index 0000000..c31d03e --- /dev/null +++ b/.github/actions/extract-version/action.yml @@ -0,0 +1,62 @@ +name: Extract Version +description: > + Extracts the version from the nearest git tag matching v... + If HEAD is exactly on that tag, snapshot=false. Otherwise snapshot=true. + +outputs: + major: + description: Major version number + value: ${{ steps.extract.outputs.major }} + minor: + description: Minor version number + value: ${{ steps.extract.outputs.minor }} + patch: + description: Patch version number + value: ${{ steps.extract.outputs.patch }} + snapshot: + description: "true if HEAD is not on a release tag, false if it is" + value: ${{ steps.extract.outputs.snapshot }} + version: + description: "Full version string, e.g. 2.0.67 or 2.0.67-SNAPSHOT" + value: ${{ steps.extract.outputs.version }} + +runs: + using: composite + steps: + - name: Extract version from nearest tag + id: extract + shell: bash + run: | + TAG_PATTERN="^v([0-9]+)\.([0-9]+)\.([0-9]+)$" + + # Check if HEAD itself carries a matching tag + HEAD_TAG=$(git tag --points-at HEAD | grep -E "$TAG_PATTERN" | head -1) + + if [[ -n "$HEAD_TAG" ]]; then + TAG="$HEAD_TAG" + SNAPSHOT="false" + else + # Find the nearest ancestor tag matching strict semver format + TAG=$(git describe --tags --abbrev=0 --match "v[0-9]*.[0-9]*.[0-9]*" 2>/dev/null) + + if [[ -z "$TAG" ]] || [[ ! "$TAG" =~ $TAG_PATTERN ]]; then + echo "ERROR: No tag matching v.. found in git history." >&2 + exit 1 + fi + SNAPSHOT="true" + fi + + # Parse the version components + [[ "$TAG" =~ $TAG_PATTERN ]] + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + PATCH="${BASH_REMATCH[3]}" + + echo "Found tag: $TAG (snapshot=$SNAPSHOT)" + VERSION="${MAJOR}.${MINOR}.${PATCH}" + [[ "$SNAPSHOT" == "true" ]] && VERSION="${VERSION}-SNAPSHOT" + echo "major=$MAJOR" >> "$GITHUB_OUTPUT" + echo "minor=$MINOR" >> "$GITHUB_OUTPUT" + echo "patch=$PATCH" >> "$GITHUB_OUTPUT" + echo "snapshot=$SNAPSHOT" >> "$GITHUB_OUTPUT" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f5dfb91..bff33ca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,9 +3,8 @@ on: pull_request: branches: - master - push: - branches: - - master + workflow_dispatch: + jobs: maven-package: runs-on: ubuntu-24.04 @@ -15,8 +14,10 @@ jobs: fetch-depth: 0 - uses: actions/setup-java@v5 with: - java-version: 17.0.13 - distribution: liberica + java-version: '17' + distribution: zulu + - name: Print Java and Maven versions + run: mvn --version - name: Cache Maven dependencies uses: actions/cache@v4 with: @@ -27,7 +28,7 @@ jobs: ${{ runner.os }}-maven- ${{ runner.os }}- - name: Run maven build - run: mvn verify -PprettierCheck -Dprettier.nodePath=node -Dprettier.npmPath=npm + run: mvn verify -PprettierCheck -Dprettier.nodePath=node -Dprettier.npmPath=npm -ntp - name: codecov uses: codecov/codecov-action@v5 with: diff --git a/.github/workflows/deploy-snapshot.yml b/.github/workflows/deploy-snapshot.yml new file mode 100644 index 0000000..30a3cdc --- /dev/null +++ b/.github/workflows/deploy-snapshot.yml @@ -0,0 +1,79 @@ +name: Publish Snapshot + +concurrency: + group: deploy-master + cancel-in-progress: false + +on: + push: + branches: + - master + - 187-create-mobilitydata-maven-packages # TEMPORARY: remove after testing + workflow_dispatch: # Manual trigger + +env: + java_version: '17' + java_distribution: 'zulu' + +jobs: + publish-snapshot: + if: "github.event_name == 'workflow_dispatch' || !contains(github.event.head_commit.message, 'ci skip')" + runs-on: ubuntu-24.04 + env: + HAS_1PASSWORD: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN != '' && vars.ONE_PASSWORD_SECRET_REFERENCES != '' }} + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: Set up JDK ${{ env.java_version }}-${{ env.java_distribution }} + uses: actions/setup-java@v5 + with: + java-version: ${{ env.java_version }} + distribution: ${{ env.java_distribution }} + - name: Print Java and Maven versions + run: mvn --version + - name: Cache Maven dependencies + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + ${{ runner.os }}-maven- + ${{ runner.os }}- + - name: Load secrets from 1Password + if: env.HAS_1PASSWORD == 'true' + uses: MobilityData/gtfs-validator/.github/actions/extract-1password-secret@master + with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + VARIABLES_TO_EXTRACT: 'MAVEN_GPG_PASSPHRASE, MAVEN_GPG_PRIVATE_KEY, MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME, MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD' + ONE_PASSWORD_SECRET_REFERENCES: ${{ vars.ONE_PASSWORD_SECRET_REFERENCES }} + - name: Load secrets from GitHub secrets (fallback for forks without 1Password) + if: env.HAS_1PASSWORD != 'true' + env: + GPG_KEY: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + GPG_PASS: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + MVN_USER: ${{ secrets.MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME }} + MVN_PASS: ${{ secrets.MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD }} + run: | + { + echo "MAVEN_GPG_PASSPHRASE=$GPG_PASS" + echo "MAVEN_GPG_PRIVATE_KEY<> "$GITHUB_ENV" + - name: Stage artifacts + run: mvn deploy -Ppublication -Dprettier.skip=true -ntp + - name: Publish snapshot to Maven Central + env: + JRELEASER_GPG_PASSPHRASE: ${{ env.MAVEN_GPG_PASSPHRASE }} + JRELEASER_GPG_SECRET_KEY: ${{ env.MAVEN_GPG_PRIVATE_KEY }} + run: mvn jreleaser:deploy -Djreleaser.output.directory=out -ntp + - name: Upload JReleaser output + if: always() + uses: actions/upload-artifact@v4 + with: + name: jreleaser-snapshot-logs + path: out/ diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 9b0a877..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Deploy Maven Central - -concurrency: - group: deploy-master - cancel-in-progress: false - -on: - push: - branches: - - master -env: - JFROG_USER: ${{ secrets.ARTIFACTORY_AUTH_USER }} - JFROG_PASS: ${{ secrets.ARTIFACTORY_AUTH_TOKEN }} - SONATYPE_GPG_KEY_BASE64: ${{ secrets.SONATYPE_GPG_KEY_BASE64 }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SONATYPE_GPG_KEY_PASSWORD: ${{ secrets.SONATYPE_GPG_KEY_PASSWORD }} - NVD_API_KEY: ${{ secrets.NVD_API_KEY }} -jobs: - maven-package: - if: github.event_name == 'push' && !contains(github.event.head_commit.message, 'ci skip') - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - name: Copy maven settings - run: | - wget https://raw.githubusercontent.com/entur/ror-maven-settings/master/.m2/settings.xml -O .github/workflows/settings.xml - - uses: actions/setup-java@v5 - with: - java-version: 17.0.13 - distribution: liberica - - name: Cache Maven dependencies - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - ${{ runner.os }}-maven- - ${{ runner.os }}- - - name: Run maven build - run: mvn package -s .github/workflows/settings.xml -PprettierCheck -Dprettier.nodePath=node -Dprettier.npmPath=npm - - name: Upload artifact - uses: actions/upload-artifact@v4.6.2 - with: - path: gbfs-validator-java/target/*.jar - publish-release: - if: github.repository_owner == 'entur' && github.event_name == 'push' - name: Publish release to maven central - uses: entur/gha-maven-central/.github/workflows/maven-publish.yml@v1 - secrets: inherit - with: - push_to_repo: true - snapshot: false - next_version: '' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..d719077 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,100 @@ +name: Release + +# Triggered by GitHub release events: +# - Creating a pre-release with tag vX.Y.Z → builds and stages artifacts to Maven Central +# (USER_MANAGED, pending). Review them at https://central.sonatype.com, then convert +# the pre-release to a full release when satisfied. +# - Publishing a full release → rebuilds and publishes artifacts to Maven Central immediately. +# +# The project version is derived from the git tag (e.g. v3.0.0 → 3.0.0) and applied to all +# modules in-place via versions:set before building. No pom.xml version commits are needed. +on: + release: + types: [prereleased, released] + +env: + java_version: '17' + java_distribution: 'zulu' + +jobs: + release: + runs-on: ubuntu-24.04 + permissions: + contents: write + env: + HAS_1PASSWORD: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN != '' && vars.ONE_PASSWORD_SECRET_REFERENCES != '' }} + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + # Check out the exact tagged commit so the version is correctly resolved from the tag. + ref: ${{ github.event.release.tag_name }} + - name: Set up JDK ${{ env.java_version }}-${{ env.java_distribution }} + uses: actions/setup-java@v5 + with: + java-version: ${{ env.java_version }} + distribution: ${{ env.java_distribution }} + - name: Print Java and Maven versions + run: mvn --version + - name: Cache Maven dependencies + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + ${{ runner.os }}-maven- + ${{ runner.os }}- + - name: Load secrets from 1Password + if: env.HAS_1PASSWORD == 'true' + uses: MobilityData/gtfs-validator/.github/actions/extract-1password-secret@master + with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + VARIABLES_TO_EXTRACT: 'MAVEN_GPG_PASSPHRASE, MAVEN_GPG_PRIVATE_KEY, MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME, MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD' + ONE_PASSWORD_SECRET_REFERENCES: ${{ vars.ONE_PASSWORD_SECRET_REFERENCES }} + - name: Load secrets from GitHub secrets (fallback for forks without 1Password) + if: env.HAS_1PASSWORD != 'true' + env: + GPG_KEY: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + GPG_PASS: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + MVN_USER: ${{ secrets.MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME }} + MVN_PASS: ${{ secrets.MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD }} + run: | + { + echo "MAVEN_GPG_PASSPHRASE=$GPG_PASS" + echo "MAVEN_GPG_PRIVATE_KEY<> "$GITHUB_ENV" + - name: Set release version from tag + run: | + TAG="${{ github.event.release.tag_name }}" + VERSION="${TAG#v}" + echo "Setting version: $VERSION" + mvn --batch-mode -ntp versions:set -DnewVersion="$VERSION" -DprocessAllModules=true -DgenerateBackupPoms=false + - name: Stage artifacts + run: mvn deploy -Ppublication -Dprettier.skip=true -ntp + - name: Deploy to Maven Central + # prereleased: USER_MANAGED — artifacts sit pending in the portal for review. + # released: AUTOMATIC — artifacts are published immediately after validation. + # jreleaser:deploy only handles Maven Central; GitHub release management is done by the GitHub UI. + env: + JRELEASER_DEPLOY_MAVEN_MAVENCENTRAL_SONATYPE_PUBLISHING_TYPE: ${{ github.event.action == 'prereleased' && 'USER_MANAGED' || 'AUTOMATIC' }} + JRELEASER_GPG_PASSPHRASE: ${{ env.MAVEN_GPG_PASSPHRASE }} + JRELEASER_GPG_SECRET_KEY: ${{ env.MAVEN_GPG_PRIVATE_KEY }} + run: mvn jreleaser:deploy -Djreleaser.output.directory=out -ntp + - name: Upload CLI fat jar to GitHub release + run: | + gh release upload "${{ github.event.release.tag_name }}" \ + gbfs-validator-java-cli/target/gbfs-validator-cli.jar \ + --clobber + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload JReleaser output + if: always() + uses: actions/upload-artifact@v4 + with: + name: jreleaser-release-logs + path: out/ diff --git a/.gitignore b/.gitignore index 0bf1286..b6868e8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,7 @@ buildNumber.properties .mvn/timing.properties # https://github.com/takari/maven-wrapper#usage-without-binary-jar .mvn/wrapper/maven-wrapper.jar +# generated by maven-git-versioning-extension +.git-versioned-pom.xml .vscode diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml new file mode 100644 index 0000000..76a9ecb --- /dev/null +++ b/.mvn/extensions.xml @@ -0,0 +1,10 @@ + + + + me.qoomon + maven-git-versioning-extension + 9.11.0 + + diff --git a/.mvn/maven-git-versioning-extension.xml b/.mvn/maven-git-versioning-extension.xml new file mode 100644 index 0000000..7e2ce87 --- /dev/null +++ b/.mvn/maven-git-versioning-extension.xml @@ -0,0 +1,23 @@ + + + + + + + ${version} + + + + + ${describe.tag.version.major}.${describe.tag.version.minor}.${describe.tag.version.patch.next}-SNAPSHOT + + + + + ${describe.tag.version.major}.${describe.tag.version.minor}.${describe.tag.version.patch.next}-SNAPSHOT + + + diff --git a/gbfs-validator-java-api/pom.xml b/gbfs-validator-java-api/pom.xml index c5cc643..eea2b1d 100644 --- a/gbfs-validator-java-api/pom.xml +++ b/gbfs-validator-java-api/pom.xml @@ -5,13 +5,14 @@ org.mobilitydata gbfs-validator-java-parent - 2.0.67 + + 0.0.0-placeholder gbfs-validator-java-api gbfs-validator-java-api gbfs-validator-java-api - https://github.com/entur/gbfs-validator-java + https://github.com/MobilityData/gbfs-validator-java Apache License, Version 2.0 @@ -134,13 +135,13 @@ org.mobilitydata gbfs-validator-java-loader - 2.0.67 + ${project.version} org.mobilitydata gbfs-validator-java - 2.0.67 + ${project.version} com.google.guava diff --git a/gbfs-validator-java-cli/pom.xml b/gbfs-validator-java-cli/pom.xml index 75d9c44..dbc13e7 100644 --- a/gbfs-validator-java-cli/pom.xml +++ b/gbfs-validator-java-cli/pom.xml @@ -6,7 +6,8 @@ org.mobilitydata gbfs-validator-java-parent - 2.0.67 + + 0.0.0-placeholder gbfs-validator-java-cli @@ -25,6 +26,8 @@ 0.8.14 + + true @@ -115,7 +118,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.6.1 + 3.6.2 package @@ -123,6 +126,11 @@ shade + + false org.entur.gbfs.validator.cli.GbfsValidatorCli @@ -131,12 +139,16 @@ gbfs-validator-cli - + *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA + META-INF/versions/** + module-info.class diff --git a/gbfs-validator-java-loader/pom.xml b/gbfs-validator-java-loader/pom.xml index 9018146..73bad34 100644 --- a/gbfs-validator-java-loader/pom.xml +++ b/gbfs-validator-java-loader/pom.xml @@ -6,7 +6,8 @@ org.mobilitydata gbfs-validator-java-parent - 2.0.67 + + 0.0.0-placeholder gbfs-validator-java-loader diff --git a/gbfs-validator-java/pom.xml b/gbfs-validator-java/pom.xml index d633be2..a8673f7 100644 --- a/gbfs-validator-java/pom.xml +++ b/gbfs-validator-java/pom.xml @@ -4,20 +4,21 @@ org.mobilitydata gbfs-validator-java-parent - 2.0.67 + + 0.0.0-placeholder gbfs-validator-java - 2.0.67 + 0.0.0-placeholder jar gbfs-validator-java Validate GBFS feeds - https://github.com/entur/gbfs-validator-java + https://github.com/MobilityData/gbfs-validator-java - Entur AS - http://www.entur.org/ + MobilityData + https://mobilitydata.org/ diff --git a/pom.xml b/pom.xml index df76ad2..aabf66b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,16 +4,17 @@ org.mobilitydata gbfs-validator-java-parent - 2.0.67 + + 0.0.0-placeholder pom GBFS Validator Parent Aggregator POM for GBFS Validator modules - https://github.com/entur/gbfs-validator-java + https://github.com/MobilityData/gbfs-validator-java - Entur AS - https://www.entur.org/ + MobilityData + https://mobilitydata.org/ @@ -51,7 +52,7 @@ HEAD - 1.20.0 + 1.23.0 5.2.0.4988 2.1.0 0.22 @@ -68,6 +69,11 @@ ALWAYS true + + false @@ -76,6 +82,8 @@ RELEASE https://central.sonatype.com/api/v1/publisher target/staging-deploy + ${env.MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME} + ${env.MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD} @@ -88,13 +96,15 @@ true true target/staging-deploy + ${env.MAVEN_CENTRAL_PORTAL_TOKEN_USERNAME} + ${env.MAVEN_CENTRAL_PORTAL_TOKEN_PASSWORD} - false + true true