From cb1468d8b302ff19b4229060c6a8220c07e732c9 Mon Sep 17 00:00:00 2001 From: matthew16550 Date: Wed, 8 Dec 2021 12:42:42 +1100 Subject: [PATCH] Add artifact signing to CI workflow & publish signature files in snapshot releases. --- .github/scripts/release.sh | 19 +++++++----- .github/scripts/release_snapshot.sh | 32 ++++++++++++++------ .github/workflows/ci.yml | 47 ++++++++++++++++++++++++----- docs/releasing.md | 11 +++++++ pom.xml | 28 +++++++++++++++++ 5 files changed, 113 insertions(+), 24 deletions(-) diff --git a/.github/scripts/release.sh b/.github/scripts/release.sh index e78a64815..e18a1487e 100755 --- a/.github/scripts/release.sh +++ b/.github/scripts/release.sh @@ -1,13 +1,18 @@ #!/usr/bin/env bash set -ex -mv plantuml.jar "plantuml-${POM_VERSION}.jar" -mv plantuml-javadoc.jar "plantuml-${POM_VERSION}-javadoc.jar" -mv plantuml-sources.jar "plantuml-${POM_VERSION}-sources.jar" +RELEASE_DIR="target/github_release" -gh release create --target "${GITHUB_SHA}" "${TAG}" \ - "plantuml-${POM_VERSION}.jar" \ - "plantuml-${POM_VERSION}-javadoc.jar" \ - "plantuml-${POM_VERSION}-sources.jar" +mkdir "${RELEASE_DIR}" + +ln -s "../plantuml.jar" "${RELEASE_DIR}/plantuml-${POM_VERSION}.jar" +ln -s "../plantuml-javadoc.jar" "${RELEASE_DIR}/plantuml-${POM_VERSION}-javadoc.jar" +ln -s "../plantuml-sources.jar" "${RELEASE_DIR}/plantuml-${POM_VERSION}-sources.jar" +# we do not release the .pom or .asc signature files here, they will be added in a later PR + +gh release create \ + --target "${GITHUB_SHA}" \ + --title "${TAG}" \ + "${TAG}" ${RELEASE_DIR}/* echo "::notice title=::Released at ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${TAG} 🎉" diff --git a/.github/scripts/release_snapshot.sh b/.github/scripts/release_snapshot.sh index 1597ba940..53dfd0efb 100755 --- a/.github/scripts/release_snapshot.sh +++ b/.github/scripts/release_snapshot.sh @@ -3,6 +3,7 @@ set -ex TAG="snapshot" DATE_TIME_UTC=$(date -u +"%F at %T (UTC)") +RELEASE_DIR="target/github_release" gh release delete "${TAG}" -y || true @@ -10,10 +11,22 @@ git tag --force "${TAG}" git push --force origin "${TAG}" -mv plantuml.jar plantuml-SNAPSHOT.jar -mv plantuml-javadoc.jar plantuml-SNAPSHOT-javadoc.jar -mv plantuml-sources.jar plantuml-SNAPSHOT-sources.jar -echo -n "${DATE_TIME_UTC}" > plantuml-SNAPSHOT-timestamp.lock +mkdir "${RELEASE_DIR}" + +ln -s "../plantuml.pom" "${RELEASE_DIR}/plantuml-SNAPSHOT.pom" +ln -s "../plantuml.jar" "${RELEASE_DIR}/plantuml-SNAPSHOT.jar" +ln -s "../plantuml-javadoc.jar" "${RELEASE_DIR}/plantuml-SNAPSHOT-javadoc.jar" +ln -s "../plantuml-sources.jar" "${RELEASE_DIR}/plantuml-SNAPSHOT-sources.jar" + +if [[ -e "target/plantuml.pom.asc" ]]; then + # signatures are optional so that forked repos can release snapshots without needing a gpg signing key + ln -s "../plantuml.pom.asc" "${RELEASE_DIR}/plantuml-SNAPSHOT.pom.asc" + ln -s "../plantuml.jar.asc" "${RELEASE_DIR}/plantuml-SNAPSHOT.jar.asc" + ln -s "../plantuml-javadoc.jar.asc" "${RELEASE_DIR}/plantuml-SNAPSHOT-javadoc.jar.asc" + ln -s "../plantuml-sources.jar.asc" "${RELEASE_DIR}/plantuml-SNAPSHOT-sources.jar.asc" +fi + +echo -n "${DATE_TIME_UTC}" > "${RELEASE_DIR}/plantuml-SNAPSHOT.timestamp" cat <<-EOF >notes.txt This is a pre-release of [the latest development work](https://github.com/plantuml/plantuml/commits/). @@ -21,10 +34,11 @@ cat <<-EOF >notes.txt ⏱ _Snapshot taken the ${DATE_TIME_UTC}_ EOF -gh release create --prerelease --target "${GITHUB_SHA}" --title "${TAG}" --notes-file notes.txt "${TAG}" \ - plantuml-SNAPSHOT.jar \ - plantuml-SNAPSHOT-javadoc.jar \ - plantuml-SNAPSHOT-sources.jar \ - plantuml-SNAPSHOT-timestamp.lock +gh release create \ + --prerelease \ + --target "${GITHUB_SHA}" \ + --title "${TAG}" \ + --notes-file notes.txt \ + "${TAG}" ${RELEASE_DIR}/* echo "::notice title=release snapshot::Snapshot released at ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${TAG} and taken the ${DATE_TIME_UTC}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23616e1be..362f14313 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,6 +78,8 @@ jobs: os: ubuntu-20.04 java_version: 8 runs-on: ${{ matrix.os }} + env: + SIGN_ARTIFACTS: ${{ secrets.ARTIFACT_SIGNING_KEY != '' }} steps: - name: Checkout the repository uses: actions/checkout@v2 @@ -107,17 +109,45 @@ jobs: - name: Test run: mvn --batch-mode test - - name: Package - if: matrix.release_from_this_build - run: mvn --batch-mode -DfinalName=plantuml -Dmaven.test.skip=true package + # The repeated "matrix.release_from_this_build" checks are messy, but I have not found a simple way to avoid them + # See https://github.com/actions/runner/issues/662 - - name: Upload jar artifacts + - name: Setup gpg + if: matrix.release_from_this_build && env.ARTIFACT_SIGNING_KEY + id: gpg + env: + ARTIFACT_SIGNING_KEY: ${{ secrets.ARTIFACT_SIGNING_KEY }} + run: | + echo "Importing key ..." + echo "${ARTIFACT_SIGNING_KEY}" | gpg --batch --import --import-options import-show + + echo "Getting key id ..." + key_id="$(echo "${ARTIFACT_SIGNING_KEY}" | gpg --batch --show-keys --with-colons | awk -F: '$1 == "sec" { print $5 }')" + echo "::set-output name=key_id::${key_id}" + + - name: Create artifacts + if: matrix.release_from_this_build + env: + GPG_KEYNAME: ${{ steps.gpg.outputs.key_id }} + GPG_PASSPHRASE: ${{ secrets.ARTIFACT_SIGNING_PASSPHRASE }} + run: | + mvn --batch-mode \ + "-DfinalName=plantuml" \ + "-Dgpg.keyname=${GPG_KEYNAME}" \ + "-Dgpg.passphrase=${GPG_PASSPHRASE}" \ + "-Dmaven.test.skip=true" \ + verify + + - name: Upload artifacts if: matrix.release_from_this_build uses: actions/upload-artifact@v2 with: # Using github.run_number here to reduce confusion when downloading & comparing artifacts from several builds - name: ${{ github.run_number }}-jars - path: target/*.jar + name: ${{ github.run_number }}-artifacts + path: | + target/*.asc + target/*.jar + target/*.pom release: needs: [ workflow_config, build ] @@ -127,10 +157,11 @@ jobs: - name: Checkout the repository uses: actions/checkout@v2 - - name: Download jar artifacts + - name: Download artifacts uses: actions/download-artifact@v2 with: - name: ${{ github.run_number }}-jars + name: ${{ github.run_number }}-artifacts + path: target - name: Create snapshot release if: needs.workflow_config.outputs.do_snapshot_release == 'true' diff --git a/docs/releasing.md b/docs/releasing.md index 2c9587327..dadfff2fe 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -10,6 +10,14 @@ Tags [cannot][3] be part of a pull request, so you need to push directly to the The release will only happen if the username making the push is matched in the CI `Configure job` step. +# Artifact Signing + +The CI workflow will sign artifacts if the `ARTIFACT_SIGNING_KEY` [GitHub secret][4] is present. This should be a +private GPG key as described [here][5]. The passphrase is stored in the `ARTIFACT_SIGNING_PASSPHRASE` secret. + +Currently, the signature files are only published as part of the [snapshot][6] releases. +In future, they will be part of the versioned releases as well. + # Releases Elsewhere PlantUML is released to other places, currently that happens outside of GitHub and is not documented here. @@ -17,3 +25,6 @@ PlantUML is released to other places, currently that happens outside of GitHub a [1]: https://github.com/plantuml/plantuml/releases [2]: https://github.com/plantuml/plantuml/actions/workflows/ci.yml [3]: https://stackoverflow.com/questions/12278660/adding-tags-to-a-pull-request +[4]: https://docs.github.com/en/actions/security-guides/encrypted-secrets +[5]: https://central.sonatype.org/publish/requirements/gpg/#generating-a-key-pair +[6]: https://github.com/plantuml/plantuml/releases/tag/snapshot diff --git a/pom.xml b/pom.xml index 989e287fc..1c90c06f0 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ https://plantuml.com + org.sonatype.oss oss-parent 7 @@ -292,5 +293,32 @@ + + + sign-artifacts + + + env.SIGN_ARTIFACTS + true + + + + + + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + +