diff --git a/.circleci/config.yml b/.circleci/config.yml index 9bb3178d7..9d641812d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,15 +20,15 @@ jobs: - run: name: publish to pypi command: | - scripts/publish-pypi.sh dist/python + jsii-release-pypi dist/python - run: name: publish to nuget command: | - scripts/publish-nuget.sh dist/dotnet + jsii-release-nuget dist/dotnet - run: name: publish to maven command: | - scripts/publish-maven.sh dist/java + jsii-release-maven dist/java workflows: version: 2 diff --git a/package-lock.json b/package-lock.json index 909107813..353a34f35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5822,6 +5822,12 @@ } } }, + "jsii-release": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsii-release/-/jsii-release-0.1.1.tgz", + "integrity": "sha512-FDr6zMsFnx4z7y9NiGskbx+5/IuV8loKZvAVOlLK/daXFBeoBgA79QVGo11Chx8BSpOXXCpnFwtZ6OL4rgZd1Q==", + "dev": true + }, "jsii-rosetta": { "version": "0.22.0", "resolved": "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-0.22.0.tgz", diff --git a/package.json b/package.json index 4f27af69b..51a8a9e25 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "isparta": "^4.1.1", "jsii": "^0.22.0", "jsii-pacmak": "^0.22.0", + "jsii-release": "^0.1.1", "mocha": "^7.0.0", "nyc": "^15.0.0", "source-map-support": "^0.5.16", diff --git a/scripts/publish-maven.sh b/scripts/publish-maven.sh deleted file mode 100755 index 257a74337..000000000 --- a/scripts/publish-maven.sh +++ /dev/null @@ -1,224 +0,0 @@ -#!/bin/bash -set -eu # we don't want "pipefail" to implement idempotency - -### -# -# Publishes all maven modules in the current directory to maven. -# -# Usage: ./publish-maven.sh DIR -# -# MAVEN_STAGING_PROFILE_ID - Maven Central (sonatype) staging profile ID (e.g. 68a05363083174) -# MAVEN_USERNAME - User name for Sonatype -# MAVEN_PASSWORD - Password for Sonatype -# MAVEN_GPG_PRIVATE_KEY - GPG private key where newlines are encoded as "\n" -# MAVEN_GPG_PRIVATE_KEY_FILE - GPG private key file (mutually exclusive with MAVEN_GPG_PRIVATE_KEY) -# MAVEN_GPG_PRIVATE_KEY_PASSPHRASE - The passphrase of the provided key. -# MAVEN_DRYRUN - Set to "true" for a dry run -# -### - -### -# -# HOW TO CREATE A GPG KEY? -# -# gpg --gen-key (use RSA, 4096, passphrase) -# -# Export and publish the public key: -# 1. gpg -a --export > public.pem -# 2. Go to https://keyserver.ubuntu.com/ and submit the public key -# -# Export and use the private key: -# 1. gpg -a --export-secret-keys > private.pem -# 2. Set MAVEN_GPG_PRIVATE_KEY_FILE =t point to `private.pem` -# or -# 3. You can also export the private key to a single line where newlines are encoded -# as "\n" and then assign it to MAVEN_GPG_PRIVATE_KEY. -# MAVEN_GPG_PRIVATE_KEY="$(echo $(cat -e private.pem) | sed 's/\$ /\\n/g' | sed 's/\$$//')" -# -### - -error() { echo "❌ $@"; exit 1; } - -[ -z "${1:-}" ] && { - echo "Usage: $(basename $0) DIR" - exit 1 -} - -cd $1 - -[ -z "${MAVEN_STAGING_PROFILE_ID:-}" ] && error "MAVEN_STAGING_PROFILE_ID is required" -[ -z "${MAVEN_USERNAME:-}" ] && error "MAVEN_USERNAME is required" -[ -z "${MAVEN_PASSWORD:-}" ] && error "MAVEN_PASSWORD is required" - -[ -z "${MAVEN_GPG_PRIVATE_KEY_PASSPHRASE:-}" ] && error "MAVEN_GPG_PRIVATE_KEY_PASSPHRASE is required" -[ -z "${MAVEN_GPG_PRIVATE_KEY_FILE:-}" ] && [ -z "${MAVEN_GPG_PRIVATE_KEY:-}" ] && error "MAVEN_GPG_PRIVATE_KEY_FILE or MAVEN_GPG_PRIVATE_KEY is required" -[ -n "${MAVEN_GPG_PRIVATE_KEY:-}" ] && [ -n "${MAVEN_GPG_PRIVATE_KEY_FILE:-}" ] && error "Cannot specify both MAVEN_GPG_PRIVATE_KEY and MAVEN_GPG_PRIVATE_KEY_FILE" - -if [[ -n "${MAVEN_DRYRUN:-}" ]]; then - echo "===========================================" - echo " 🏜️ DRY-RUN MODE 🏜️" - echo - echo "Set FOR_REAL=true to do actual publishing!" - echo "===========================================" - mvn="echo mvn" - dry_run=true -else - mvn=mvn - dry_run=false -fi - -#--------------------------------------------------------------------------------------------------------------------------------------- -# Import private GPG key -#--------------------------------------------------------------------------------------------------------------------------------------- - -echo "Importing GPG key..." >&2 - -# GnuPG will occasionally bail out with "gpg: failed: Inappropriate ioctl for device", the following attempts to fix -export GNUPGHOME=$(mktemp -d) -export GPG_TTY=$(tty) - - -if [ -n "${MAVEN_GPG_PRIVATE_KEY}" ]; then - MAVEN_GPG_PRIVATE_KEY_FILE="${GNUPGHOME}/private.pem" - echo -e "${MAVEN_GPG_PRIVATE_KEY}" > ${MAVEN_GPG_PRIVATE_KEY_FILE} -fi - -gpg --allow-secret-key-import --batch --yes --no-tty --import "${MAVEN_GPG_PRIVATE_KEY_FILE}" || { - echo "❌ GPG key import failed" - exit 1 -} - -gpg_key_id=$(gpg --list-keys --with-colons | grep pub | cut -d: -f5) -echo "gpg_key_id=${gpg_key_id}" - -GPG_PASSPHRASE_FROM_STDIN="--passphrase-fd 0" -if [[ "$(uname)" == "Darwin" ]]; then - # On Mac, we must pass this to disable a prompt for - # passphrase, but option is not recognized on Linux. - GPG_PASSPHRASE_FROM_STDIN="${GPG_PASSPHRASE_FROM_STDIN} --pinentry-mode loopback" -fi -export GPG_PASSPHRASE_FROM_STDIN - -poms="$(find . -name '*.pom')" -if [ -z "${poms}" ]; then - echo "❌ No JARS to publish: no .pom files found under $PWD" - exit 1 -fi - -echo "📦 Publishing to Maven Central" -staging=$(mktemp -d) -workdir=$(mktemp -d) - -# Create a settings.xml file with the user+password for maven -mvn_settings="${workdir}/mvn-settings.xml" -cat > ${mvn_settings} <<-EOF - - - - - ossrh - ${MAVEN_USERNAME} - ${MAVEN_PASSWORD} - - - -EOF - -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo " Preparing repository" -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - -# Sign and stage our artifacts into a local directory -for pom in "${poms}"; do - $mvn --settings=${mvn_settings} gpg:sign-and-deploy-file \ - -Durl=file://${staging} \ - -DrepositoryId=maven-central \ - -Dgpg.homedir=${GNUPGHOME} \ - -Dgpg.keyname=0x${gpg_key_id} \ - -Dgpg.passphrase=${MAVEN_GPG_PRIVATE_KEY_PASSPHRASE} \ - -DpomFile=${pom} \ - -Dfile=${pom/.pom/.jar} \ - -Dsources=${pom/.pom/-sources.jar} \ - -Djavadoc=${pom/.pom/-javadoc.jar} -done - - -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo " Deploying and closing repository..." -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - -staging_output="${workdir}/deploy-output.txt" -$mvn --settings=${mvn_settings} \ - org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:deploy-staged-repository \ - -DrepositoryDirectory=${staging} \ - -DnexusUrl=${MAVEN_ENDPOINT:-https://oss.sonatype.org} \ - -DserverId=ossrh \ - -DautoReleaseAfterClose=true \ - -DstagingProfileId=${MAVEN_STAGING_PROFILE_ID} | tee ${staging_output} - -# we need to consule PIPESTATUS sinec "tee" is the last command -if [ ${PIPESTATUS[0]} -ne 0 ]; then - echo "❌ Repository deployment failed" - exit 1 -fi - -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo " Releasing repository" -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - -# Extract the ID of the closed repository from the log output of "deploy-staged-repository" -# This is because "deploy-staged-repository" doesn't seem to support autoReleaseAfterClose -# See https://issues.sonatype.org/browse/OSSRH-42487 -if $dry_run; then - echo 'Closing staging repository with ID "dummyrepo"' > ${staging_output} -fi - -repository_id="$(cat ${staging_output} | grep "Closing staging repository with ID" | cut -d'"' -f2)" -if [ -z "${repository_id}" ]; then - echo "❌ Unable to extract repository ID from deploy-staged-repository output." - echo "This means it failed to close or there was an unexpected problem." - echo "At any rate, we can't release it. Sorry" - exit 1 -fi - -echo "Repository ID: ${repository_id}" - -# Create a dummy pom.xml because the "release" goal needs one, but it doesn't care about it at all -release_pom="${workdir}/release-pom.xml" -cat > ${release_pom} < - - 4.0.0 - dummy - dummy - 0.0.0 - -HERE - -# Release! -release_output="${workdir}/release-output.txt" -$mvn --settings ${mvn_settings} -f ${release_pom} \ - org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:release \ - -DserverId=ossrh \ - -DnexusUrl=${MAVEN_ENDPOINT:-https://oss.sonatype.org} \ - -DstagingProfileId=${MAVEN_STAGING_PROFILE_ID} \ - -DstagingRepositoryId=${repository_id} | tee ${release_output} - -# If release failed, check if this was caused because we are trying to publish -# the same version again, which is not an error. The magic string "does not -# allow updating artifact" for a ".pom" file indicates that we are trying to -# override an existing version. Otherwise, fail! -if [ ${PIPESTATUS[0]} -ne 0 ]; then - if cat ${release_output} | grep "does not allow updating artifact" | grep -q ".pom"; then - echo "⚠️ Artifact already published. Skipping" - else - echo "❌ Release failed" - exit 1 - fi -fi - -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo "✅ All Done!" diff --git a/scripts/publish-npm.sh b/scripts/publish-npm.sh deleted file mode 100755 index 9b2d1823b..000000000 --- a/scripts/publish-npm.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -set -eu - -[ -z "${1:-}" ] && { - echo "Usage: $(basename $0) DIR" - exit 1 -} - -[ -z "${NPM_TOKEN:-}" ] && { - echo "NPM_TOKEN is required" - exit 1 -} - -log=$(mktemp -d)/npmlog.txt - -echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc -npm publish $1/* 2>&1 | tee $log -exit_code="${PIPESTATUS[0]}" - -echo -echo "===============================================================" - -if [ ${exit_code} -ne 0 ]; then - - if cat $log | grep -q "You cannot publish over the previously published versions"; then - echo "SKIPPING: already published" - exit 0 - fi - - echo "ERROR" - exit 1 -fi - -echo "SUCCESS" \ No newline at end of file diff --git a/scripts/publish-nuget.sh b/scripts/publish-nuget.sh deleted file mode 100755 index 137b39917..000000000 --- a/scripts/publish-nuget.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash -scriptdir=$(cd $(dirname $0) && pwd) -set -eu # we don't want "pipefail" to implement idempotency - -### -# -# Publishes all nupkg to nuget -# -# Usage: ./publish-maven.sh [DIR] -# -# NUGET_API_KEY: API key for nuget -# -### - -[ -n "${1:-}" ] && cd $1 - -if [ -z "${NUGET_API_KEY:-}" ]; then - echo "NUGET_API_KEY is required" - exit 1 -fi - -packages=$(find . -name *.nupkg -not -iname *.symbols.nupkg) -if [ -z "${packages}" ]; then - echo "❌ No *.nupkg files found under $PWD. Nothing to publish" - exit 1 -fi - -echo "Publishing NuGet packages..." - -nuget_source="https://api.nuget.org/v3/index.json" -nuget_symbol_source="https://nuget.smbsrc.net/" - -log=$(mktemp -d)/log.txt - -for package_dir in "${packages}"; do - echo "📦 Publishing ${package_dir} to NuGet" - ( - cd $(dirname $package_dir) - nuget_package_name=$(basename $package_dir) - nuget_package_base=${nuget_package_name%.nupkg} - - [ -f "${nuget_package_base}.snupkg" ] || echo "⚠️ No symbols package was found!" - - # The .snupkg will be published at the same time as the .nupkg if both are in the current folder (which is the case) - dotnet nuget push $nuget_package_name -k ${NUGET_API_KEY} -s ${nuget_source} | tee ${log} - exit_code="${PIPESTATUS[0]}" - - # If push failed, check if this was caused because we are trying to publish - # the same version again, which is not an error by searching for a magic string in the log - # ugly, yes! - if cat ${log} | grep -q "already exists and cannot be modified"; then - echo "⚠️ Artifact already published. Skipping" - elif [ "${exit_code}" -ne 0 ]; then - echo "❌ Release failed" - exit 1 - fi - ) -done - -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo "✅ All Done!" diff --git a/scripts/publish-pypi.sh b/scripts/publish-pypi.sh deleted file mode 100755 index 6c4a58c38..000000000 --- a/scripts/publish-pypi.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -set -euo pipefail - -[ -n "${1:-}" ] && cd $1 - -[ -z "${TWINE_USERNAME:-}" ] && { - echo "Missing TWINE_USERNAME" - exit 1 -} - -[ -z "${TWINE_PASSWORD:-}" ] && { - echo "Missing TWINE_PASSWORD" - exit 1 -} - -if [ -z "$(ls *.whl)" ]; then - echo "cannot find any .whl files in $PWD" - exit 1 -fi - -python3 -m pip install --user --upgrade twine -python3 -m twine upload --skip-existing *