diff --git a/.github/workflows/Tools.java b/.github/workflows/Tools.java new file mode 100644 index 0000000..32c63c3 --- /dev/null +++ b/.github/workflows/Tools.java @@ -0,0 +1,162 @@ +/* + * Copyright © 2024 Mark Raynsford https://www.io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.TreeMap; + +public final class Tools +{ + private static final TreeMap OPS = + new TreeMap<>(); + + static { + final var opsList = List.of( + new ShowProjectVersion(), + new ShowProjectIsSnapshot() + ); + + for (final var op : opsList) { + OPS.put(op.name(), op); + } + } + + private Tools() + { + + } + + private interface OpType + { + String name(); + + void execute(String[] args) + throws Exception; + } + + private static String getProjectVersion( + final File file) + throws Exception + { + final var documentBuilders = + DocumentBuilderFactory.newInstance(); + final var documentBuilder = + documentBuilders.newDocumentBuilder(); + final var document = + documentBuilder.parse(file); + + final var xPathFactory = + XPathFactory.newInstance(); + final var xPath = + xPathFactory.newXPath(); + + final var nodes = + (NodeList) xPath.evaluate( + "//project/version", + document, + XPathConstants.NODESET + ); + + for (var i = 0; i < nodes.getLength(); i++) { + final var node = nodes.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + return node.getTextContent().trim(); + } + } + + throw new IOException( + "Could not locate a //project/version node!" + ); + } + + private static final class ShowProjectVersion implements OpType + { + ShowProjectVersion() + { + + } + + @Override + public String name() + { + return "ShowProjectVersion"; + } + + @Override + public void execute( + final String[] args) + throws Exception + { + System.out.print("IO7M_PROJECT_VERSION="); + System.out.println(getProjectVersion(new File(args[1]))); + } + } + + private static final class ShowProjectIsSnapshot implements OpType + { + ShowProjectIsSnapshot() + { + + } + + @Override + public String name() + { + return "ShowProjectIsSnapshot"; + } + + @Override + public void execute( + final String[] args) + throws Exception + { + System.out.print("IO7M_PROJECT_VERSION_IS_SNAPSHOT="); + System.out.println( + getProjectVersion(new File(args[1])).endsWith("-SNAPSHOT") + ); + } + } + + public static void main( + final String[] args) + throws Exception + { + if (args.length == 0) { + System.err.println("Usage: command"); + System.exit(1); + } + + final var op = OPS.get(args[0]); + if (op == null) { + System.err.println("Unrecognized command."); + System.err.println(" Must be one of:"); + for (final var name : OPS.keySet()) { + System.err.print(" "); + System.err.println(name); + } + System.exit(1); + } + + op.execute(args); + } +} \ No newline at end of file diff --git a/.github/workflows/deploy-release.sh b/.github/workflows/deploy-release.sh new file mode 100755 index 0000000..e25fc82 --- /dev/null +++ b/.github/workflows/deploy-release.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +fatal() +{ + echo "fatal: $1" 1>&2 + exit 1 +} + +if [ -z "${MAVEN_CENTRAL_USERNAME}" ] +then + fatal "MAVEN_CENTRAL_USERNAME is not set." +fi + +if [ -z "${MAVEN_CENTRAL_PASSWORD}" ] +then + fatal "MAVEN_CENTRAL_PASSWORD is not set." +fi + +(cat < + + + + io7m + + true + github-ci-maven-rsa-key + true + + + + + + + sonatype-nexus-snapshots + ${MAVEN_CENTRAL_USERNAME} + ${MAVEN_CENTRAL_PASSWORD} + + + sonatype-nexus-staging + ${MAVEN_CENTRAL_USERNAME} + ${MAVEN_CENTRAL_PASSWORD} + + + +EOF +) > "$HOME/.m2/settings.xml" || fatal "could not update $HOME/.m2/settings.xml" + +exec mvn \ +-Dio7m.release=true \ +-Dio7m.deployment=true \ +--batch-mode \ +--strict-checksums \ +-DskipTests=true \ +-DskipITs=true deploy diff --git a/.github/workflows/deploy-snapshot.sh b/.github/workflows/deploy-snapshot.sh new file mode 100755 index 0000000..227c79c --- /dev/null +++ b/.github/workflows/deploy-snapshot.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +fatal() +{ + echo "fatal: $1" 1>&2 + exit 1 +} + +if [ -z "${MAVEN_CENTRAL_USERNAME}" ] +then + fatal "MAVEN_CENTRAL_USERNAME is not set." +fi + +if [ -z "${MAVEN_CENTRAL_PASSWORD}" ] +then + fatal "MAVEN_CENTRAL_PASSWORD is not set." +fi + +(cat < + + + sonatype-nexus-snapshots + ${MAVEN_CENTRAL_USERNAME} + ${MAVEN_CENTRAL_PASSWORD} + + + sonatype-nexus-staging + ${MAVEN_CENTRAL_USERNAME} + ${MAVEN_CENTRAL_PASSWORD} + + + +EOF +) > "$HOME/.m2/settings.xml" || fatal "could not update $HOME/.m2/settings.xml" + +exec mvn \ +--batch-mode \ +--strict-checksums \ +-DskipTests=true \ +-DskipITs=true deploy diff --git a/.github/workflows/deploy.linux.temurin.lts.yml b/.github/workflows/deploy.linux.temurin.lts.yml new file mode 100644 index 0000000..e5d7ce2 --- /dev/null +++ b/.github/workflows/deploy.linux.temurin.lts.yml @@ -0,0 +1,28 @@ +name: deploy.linux.temurin.lts + +on: + push: + tags: [ com.io7m.jsay-* ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: JDK + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: 'temurin' + + - name: Import signing key + env: + PGP_SIGNING_KEY: ${{ secrets.PGP_SIGNING_KEY }} + run: echo "${PGP_SIGNING_KEY}" | gpg --import + + - name: Deploy release + env: + MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + run: .github/workflows/deploy-release.sh diff --git a/.github/workflows/main.linux.temurin.current.yml b/.github/workflows/main.linux.temurin.current.yml index 42f9062..40117c9 100644 --- a/.github/workflows/main.linux.temurin.current.yml +++ b/.github/workflows/main.linux.temurin.current.yml @@ -11,16 +11,28 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: JDK uses: actions/setup-java@v4 with: java-version: 22 distribution: 'temurin' + + - name: Collect project version + id: project_version + run: java .github/workflows/Tools.java ShowProjectVersion pom.xml >> "$GITHUB_OUTPUT" + + - name: Collect project snapshot + id: project_is_snapshot + run: java .github/workflows/Tools.java ShowProjectIsSnapshot pom.xml >> "$GITHUB_OUTPUT" + - name: Build - run: mvn --errors clean verify site + run: mvn --batch-mode --strict-checksums --errors clean verify site + - name: Upload test logs uses: actions/upload-artifact@v4 if: always() with: name: test-logs path: ./com.io7m.jsay.tests/target/surefire-reports + diff --git a/.github/workflows/main.linux.temurin.lts.yml b/.github/workflows/main.linux.temurin.lts.yml index 6f3ef77..f587bd1 100644 --- a/.github/workflows/main.linux.temurin.lts.yml +++ b/.github/workflows/main.linux.temurin.lts.yml @@ -11,21 +11,41 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: JDK uses: actions/setup-java@v4 with: java-version: 21 distribution: 'temurin' + + - name: Collect project version + id: project_version + run: java .github/workflows/Tools.java ShowProjectVersion pom.xml >> "$GITHUB_OUTPUT" + + - name: Collect project snapshot + id: project_is_snapshot + run: java .github/workflows/Tools.java ShowProjectIsSnapshot pom.xml >> "$GITHUB_OUTPUT" + - name: Build - run: mvn --errors clean verify site + run: mvn --batch-mode --strict-checksums --errors clean verify site + - name: Upload test logs uses: actions/upload-artifact@v4 if: always() with: name: test-logs path: ./com.io7m.jsay.tests/target/surefire-reports + - name: Coverage uses: codecov/codecov-action@v4.3.1 with: token: ${{ secrets.CODECOV_TOKEN }} file: com.io7m.jsay.tests/target/site/jacoco-aggregate/jacoco.xml + + - name: Deploy snapshot + if: ${{ steps.project_is_snapshot.outputs.IO7M_PROJECT_VERSION_IS_SNAPSHOT == 'true' }} + env: + MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + run: .github/workflows/deploy-snapshot.sh + diff --git a/.github/workflows/main.windows.temurin.current.yml b/.github/workflows/main.windows.temurin.current.yml index a5a302f..3811530 100644 --- a/.github/workflows/main.windows.temurin.current.yml +++ b/.github/workflows/main.windows.temurin.current.yml @@ -11,16 +11,28 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v4 + - name: JDK uses: actions/setup-java@v4 with: java-version: 22 distribution: 'temurin' + + - name: Collect project version + id: project_version + run: java .github/workflows/Tools.java ShowProjectVersion pom.xml >> "$GITHUB_OUTPUT" + + - name: Collect project snapshot + id: project_is_snapshot + run: java .github/workflows/Tools.java ShowProjectIsSnapshot pom.xml >> "$GITHUB_OUTPUT" + - name: Build - run: mvn --errors clean verify site + run: mvn --batch-mode --strict-checksums --errors clean verify site + - name: Upload test logs uses: actions/upload-artifact@v4 if: always() with: name: test-logs path: ./com.io7m.jsay.tests/target/surefire-reports + diff --git a/.github/workflows/main.windows.temurin.lts.yml b/.github/workflows/main.windows.temurin.lts.yml index b1b8b73..f3a7247 100644 --- a/.github/workflows/main.windows.temurin.lts.yml +++ b/.github/workflows/main.windows.temurin.lts.yml @@ -11,16 +11,28 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v4 + - name: JDK uses: actions/setup-java@v4 with: java-version: 21 distribution: 'temurin' + + - name: Collect project version + id: project_version + run: java .github/workflows/Tools.java ShowProjectVersion pom.xml >> "$GITHUB_OUTPUT" + + - name: Collect project snapshot + id: project_is_snapshot + run: java .github/workflows/Tools.java ShowProjectIsSnapshot pom.xml >> "$GITHUB_OUTPUT" + - name: Build - run: mvn --errors clean verify site + run: mvn --batch-mode --strict-checksums --errors clean verify site + - name: Upload test logs uses: actions/upload-artifact@v4 if: always() with: name: test-logs path: ./com.io7m.jsay.tests/target/surefire-reports +