diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..2f75d1f8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,58 @@ +name: Release + +env: + GH_TOKEN: ${{ github.token }} + +on: + workflow_dispatch: + inputs: + release_type: + type: choice + description: "Release type:" + required: true + options: + - bug fix (PATCH) + - new feature (MINOR) + release_title: + description: "The title of the release" + required: true + +jobs: + update-version: + runs-on: ubuntu-20.04 # latest + permissions: + contents: write # allow push + pull-requests: write # allow making PR + + steps: + - name: Checkout Sources + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Make new release + env: + Title: ${{ github.event.inputs.release_title }} + run: | + # Escape special characters + Title=$(echo ${Title//[\"]\\\"}) + Title=$(echo ${Title//[\']\\\'}) + Title=$(echo ${Title//[\$]}) + + ./utils/publish-release.sh "${{ github.event.inputs.release_type }}" "$Title" + + - name: configure AWS credentials (Release) + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ secrets.AWS_CI_RELEASE_ROLE }} + aws-region: us-east-1 + + - name: "Create VERSION file and trigger release" + run: | + version=$(git describe --tags --abbrev=0) + version_without_v=$(echo ${version} | cut -f2 -dv) + echo "${version_without_v}" > VERSION + + zip VERSION.zip VERSION + export S3_URL=$(aws secretsmanager get-secret-value --secret-id ci/python_v2_version --query "SecretString" | cut -f2 -d\") + aws s3 cp VERSION.zip $S3_URL diff --git a/README.md b/README.md index 4fe9517a..07aec71c 100644 --- a/README.md +++ b/README.md @@ -99,3 +99,5 @@ We need your help in making this SDK great. Please participate in the community ## License This library is licensed under the [Apache 2.0 License](./documents/LICENSE). + +Latest released version: v1.12.0 diff --git a/continuous-delivery/pip-install-with-retry.py b/codebuild/cd/pip-install-with-retry.py similarity index 100% rename from continuous-delivery/pip-install-with-retry.py rename to codebuild/cd/pip-install-with-retry.py diff --git a/continuous-delivery/publish_to_prod_pypi.yml b/codebuild/cd/publish-to-prod-pypi.yml similarity index 58% rename from continuous-delivery/publish_to_prod_pypi.yml rename to codebuild/cd/publish-to-prod-pypi.yml index 0e72e510..859c0cbc 100644 --- a/continuous-delivery/publish_to_prod_pypi.yml +++ b/codebuild/cd/publish-to-prod-pypi.yml @@ -1,5 +1,9 @@ +# Assumes are running using the Ubuntu Codebuild standard image +# Makes a release deployment to production PyPi repo. +# +# NOTE: This script assumes that the AWS CLI-V2 is pre-installed! +# - AWS CLI-V2 is a requirement to run this script. version: 0.2 -# this image assumes Ubuntu base image phases: install: commands: @@ -8,11 +12,13 @@ phases: - export PATH=$PATH:$HOME/.local/bin - python3 -m pip install --user --upgrade pip - python3 -m pip install --user --upgrade twine setuptools wheel awscli PyOpenSSL six + - echo "\nBuild version data:" + - echo "\nPython Version:"; python3 --version pre_build: commands: - - cd aws-iot-device-sdk-python-v2 - - pypirc=$(aws secretsmanager get-secret-value --secret-id "prod/aws-sdk-python-v2/.pypirc" --query "SecretString" | cut -f2 -d\") && echo "$pypirc" > ~/.pypirc - - export PKG_VERSION=$(git describe --tags | cut -f2 -dv) + - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-python-v2 + - pypirc=$(aws secretsmanager get-secret-value --secret-id "cd/aws-sdk-python-v2-prod/.pypirc" --query "SecretString" | cut -f2 -d\") && echo "$pypirc" > ~/.pypirc + - export PKG_VERSION=$(cat $CODEBUILD_SRC_DIR/VERSION) - echo "Updating package version to ${PKG_VERSION}" - sed --in-place -E "s/__version__ = '.+'/__version__ = '${PKG_VERSION}'/" awsiot/__init__.py build: diff --git a/continuous-delivery/publish_to_test_pypi.yml b/codebuild/cd/publish-to-test-pypi.yml similarity index 58% rename from continuous-delivery/publish_to_test_pypi.yml rename to codebuild/cd/publish-to-test-pypi.yml index 809f828a..9450aa80 100644 --- a/continuous-delivery/publish_to_test_pypi.yml +++ b/codebuild/cd/publish-to-test-pypi.yml @@ -1,5 +1,9 @@ +# Assumes are running using the Ubuntu Codebuild standard image +# Makes a release deployment to test PyPi repo. +# +# NOTE: This script assumes that the AWS CLI-V2 is pre-installed! +# - AWS CLI-V2 is a requirement to run this script. version: 0.2 -# this image assumes Ubuntu base image phases: install: commands: @@ -8,11 +12,13 @@ phases: - export PATH=$PATH:$HOME/.local/bin - python3 -m pip install --user --upgrade pip - python3 -m pip install --user --upgrade twine setuptools wheel awscli PyOpenSSL six + - echo "\nBuild version data:" + - echo "\nPython Version:"; python3 --version pre_build: commands: - - pypirc=$(aws secretsmanager get-secret-value --secret-id "alpha/aws-crt-python/.pypirc" --query "SecretString" | cut -f2 -d\") && echo "$pypirc" > ~/.pypirc - - cd aws-iot-device-sdk-python-v2 - - export PKG_VERSION=$(git describe --tags | cut -f2 -dv) + - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-python-v2 + - pypirc=$(aws secretsmanager get-secret-value --secret-id "cd/aws-sdk-python-v2-test/.pypirc" --query "SecretString" | cut -f2 -d\") && echo "$pypirc" > ~/.pypirc + - export PKG_VERSION=$(cat $CODEBUILD_SRC_DIR/VERSION) - echo "Updating package version to ${PKG_VERSION}" - sed --in-place -E "s/__version__ = '.+'/__version__ = '${PKG_VERSION}'/" awsiot/__init__.py build: diff --git a/codebuild/cd/test-prod-pypi.yml b/codebuild/cd/test-prod-pypi.yml new file mode 100644 index 00000000..9777dc96 --- /dev/null +++ b/codebuild/cd/test-prod-pypi.yml @@ -0,0 +1,36 @@ +# Assumes are running using the Ubuntu Codebuild standard image +# Makes sure the release to test PyPi repository worked +# +# NOTE: This script assumes that the AWS CLI-V2 is pre-installed! +# - AWS CLI-V2 is a requirement to run this script. +version: 0.2 +phases: + install: + commands: + - sudo apt-get update -y + - sudo apt-get install python3 python3-pip -y + - python3 -m pip install --upgrade pip + - python3 -m pip install --upgrade setuptools + - echo "\nBuild version data:" + - echo "\nPython Version:"; python3 --version + + pre_build: + commands: + # Material for PubSub sample + - curl https://www.amazontrust.com/repository/AmazonRootCA1.pem --output /tmp/AmazonRootCA1.pem + - cert=$(aws secretsmanager get-secret-value --secret-id "ci/PubSub/cert" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$cert" > /tmp/certificate.pem + - key=$(aws secretsmanager get-secret-value --secret-id "ci/PubSub/key" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$key" > /tmp/privatekey.pem + - ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') + build: + commands: + - echo Build started on `date` + - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-python-v2 + - CURRENT_TAG_VERSION=$(cat $CODEBUILD_SRC_DIR/VERSION) + - python3 codebuild/cd/pip-install-with-retry.py --no-cache-dir --user awsiotsdk==$CURRENT_TAG_VERSION + # Run PubSub sample + - python3 samples/pubsub.py --endpoint ${ENDPOINT} --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --verbosity Trace + + post_build: + commands: + - echo Build completed on `date` + diff --git a/codebuild/cd/test-test-pypi.yml b/codebuild/cd/test-test-pypi.yml new file mode 100644 index 00000000..d202dcce --- /dev/null +++ b/codebuild/cd/test-test-pypi.yml @@ -0,0 +1,36 @@ +# Assumes are running using the Ubuntu Codebuild standard image +# Makes sure the release to test PyPi repository worked +# +# NOTE: This script assumes that the AWS CLI-V2 is pre-installed! +# - AWS CLI-V2 is a requirement to run this script. +version: 0.2 +phases: + install: + commands: + - sudo apt-get update -y + - sudo apt-get install python3 python3-pip -y + - python3 -m pip install --upgrade pip + - python3 -m pip install --upgrade setuptools + - echo "\nBuild version data:" + - echo "\nPython Version:"; python3 --version + + pre_build: + commands: + - curl https://www.amazontrust.com/repository/AmazonRootCA1.pem --output /tmp/AmazonRootCA1.pem + - cert=$(aws secretsmanager get-secret-value --secret-id "ci/PubSub/cert" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$cert" > /tmp/certificate.pem + - key=$(aws secretsmanager get-secret-value --secret-id "ci/PubSub/key" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$key" > /tmp/privatekey.pem + - ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') + build: + commands: + - echo Build started on `date` + - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-python-v2 + - CURRENT_TAG_VERSION=$(cat $CODEBUILD_SRC_DIR/VERSION) + # this is here because typing isn't in test-pypi, so pull it from prod instead + - python3 -m pip install typing + - python3 codebuild/cd/pip-install-with-retry.py -i https://testpypi.python.org/simple --user awsiotsdk==$CURRENT_TAG_VERSION + # Run PubSub sample + - python3 samples/pubsub.py --endpoint ${ENDPOINT} --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --verbosity Trace + + post_build: + commands: + - echo Build completed on `date` diff --git a/codebuild/cd/test-version-exists.sh b/codebuild/cd/test-version-exists.sh new file mode 100755 index 00000000..82f91339 --- /dev/null +++ b/codebuild/cd/test-version-exists.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +VERSION_FILE_PATH=$1 +if [ ! readlink -e "$VERSION_FILE_PATH" ]; then + echo "No VERSION file found! Cannot make release!" + exit 1 +else + echo "VERSION file found..." +fi +VERSION=$(cat $VERSION_FILE_PATH) + +# Make sure the version variable is populated +if [ -z "${VERSION}" ]; then + echo "VERSION file is empty!" + exit 1 +else + echo "VERSION file contains: ${VERSION}" +fi + +# Make sure the version follows the correct format: major.minor.patch +LENGTH_CHECK="${VERSION//[^.]}" +if [ ${#LENGTH_CHECK} != 2 ]; then + echo "VERSION file contains invalid version (not in format major.minor.patch)" + exit 1 +fi +# Use RegX to ensure it only contains numbers and periods +REGX_CHECK='^([0-9]+\.){0,2}(\*|[0-9]+)$' +if [[ $VERSION =~ $REGX_CHECK ]]; then + echo "VERSION file contains valid version" +else + echo "VERSION file contains invalid version (RegX validator failed)" + exit 1 +fi + +# Does PyPi have the version? If so, do not allow it! +if python3 -m pip install --no-cache-dir -vvv awsiotsdk==$VERSION; then + echo "$VERSION is already in pypi, cut a new tag if you want to upload another version." + exit 1 +fi + +echo "$VERSION currently does not exist in pypi, allowing pipeline to continue." +exit 0 diff --git a/codebuild/cd/test-version-exists.yml b/codebuild/cd/test-version-exists.yml new file mode 100644 index 00000000..877ca0b1 --- /dev/null +++ b/codebuild/cd/test-version-exists.yml @@ -0,0 +1,19 @@ +# Assumes are running using the Ubuntu Codebuild standard image +# Makes sure the version in CD has not already been released. +# Will fail the build and stop the pipeline if the version has already been released. +# +# NOTE: This script assumes that the AWS CLI-V2 is pre-installed! +# - AWS CLI-V2 is a requirement to run this script. +version: 0.2 +phases: + install: + commands: + - sudo apt-get update -y + - sudo apt-get install python3 python3-pip -y + - pip3 install --upgrade setuptools + - echo "\nBuild version data:" + - echo "\nPython Version:"; python3 --version + build: + commands: + - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-python-v2 + - bash ./codebuild/cd/test-version-exists.sh $CODEBUILD_SRC_DIR/VERSION diff --git a/continuous-delivery/test_prod_pypi.yml b/continuous-delivery/test_prod_pypi.yml deleted file mode 100644 index 9261ff5e..00000000 --- a/continuous-delivery/test_prod_pypi.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 0.2 -# this image assumes Ubuntu 14.04 base image -phases: - install: - commands: - - sudo apt-get update -y - - sudo apt-get install python3 python3-pip -y - - python3 -m pip install --upgrade pip - - python3 -m pip install --upgrade setuptools - - pre_build: - commands: - - curl https://www.amazontrust.com/repository/AmazonRootCA1.pem --output /tmp/AmazonRootCA1.pem - - cert=$(aws secretsmanager get-secret-value --secret-id "unit-test/certificate" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$cert" > /tmp/certificate.pem - - key=$(aws secretsmanager get-secret-value --secret-id "unit-test/privatekey" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$key" > /tmp/privatekey.pem - - ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - build: - commands: - - echo Build started on `date` - - cd aws-iot-device-sdk-python-v2 - - CURRENT_TAG_VERSION=$(git describe --tags | cut -f2 -dv) - - python3 continuous-delivery/pip-install-with-retry.py --no-cache-dir --user awsiotsdk==$CURRENT_TAG_VERSION - - python3 samples/basic_discovery.py --region us-east-1 --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --thing_name aws-sdk-crt-unit-test --print_discover_resp_only --verbosity Trace - - post_build: - commands: - - echo Build completed on `date` - diff --git a/continuous-delivery/test_test_pypi.yml b/continuous-delivery/test_test_pypi.yml deleted file mode 100644 index 79113c0a..00000000 --- a/continuous-delivery/test_test_pypi.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: 0.2 -# this image assumes Ubuntu 14.04 base image -phases: - install: - commands: - - sudo apt-get update -y - - sudo apt-get install python3 python3-pip -y - - python3 -m pip install --upgrade pip - - python3 -m pip install --upgrade setuptools - - pre_build: - commands: - - curl https://www.amazontrust.com/repository/AmazonRootCA1.pem --output /tmp/AmazonRootCA1.pem - - cert=$(aws secretsmanager get-secret-value --secret-id "unit-test/certificate" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$cert" > /tmp/certificate.pem - - key=$(aws secretsmanager get-secret-value --secret-id "unit-test/privatekey" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo "$key" > /tmp/privatekey.pem - - ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - build: - commands: - - echo Build started on `date` - - cd aws-iot-device-sdk-python-v2 - - CURRENT_TAG_VERSION=$(git describe --tags | cut -f2 -dv) - # this is here because typing isn't in testpypi, so pull it from prod instead - - python3 -m pip install typing - - python3 continuous-delivery/pip-install-with-retry.py -i https://testpypi.python.org/simple --user awsiotsdk==$CURRENT_TAG_VERSION - - python3 samples/basic_discovery.py --region us-east-1 --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --thing_name aws-sdk-crt-unit-test --print_discover_resp_only --verbosity Trace - - post_build: - commands: - - echo Build completed on `date` - diff --git a/continuous-delivery/test_version_exists b/continuous-delivery/test_version_exists deleted file mode 100755 index c869ec44..00000000 --- a/continuous-delivery/test_version_exists +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -e -set -x -# force a failure if there's no tag -git describe --tags -# now get the tag -CURRENT_TAG=$(git describe --tags | cut -f2 -dv) -# convert v0.2.12-2-g50254a9 to 0.2.12 -CURRENT_TAG_VERSION=$(git describe --tags | cut -f1 -d'-' | cut -f2 -dv) -# if there's a hash on the tag, then this is not a release tagged commit -if [ "$CURRENT_TAG" != "$CURRENT_TAG_VERSION" ]; then - echo "Current tag version is not a release tag, cut a new release if you want to publish." - exit 1 -fi - -if python3 -m pip install --no-cache-dir -vvv awsiotsdk==$CURRENT_TAG_VERSION; then - echo "$CURRENT_TAG_VERSION is already in pypi, cut a new tag if you want to upload another version." - exit 1 -fi - -echo "$CURRENT_TAG_VERSION currently does not exist in pypi, allowing pipeline to continue." -exit 0 diff --git a/continuous-delivery/test_version_exists.yml b/continuous-delivery/test_version_exists.yml deleted file mode 100644 index ca67e644..00000000 --- a/continuous-delivery/test_version_exists.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: 0.2 -#this build spec assumes the ubuntu 14.04 trusty image -#this build run simply verifies we haven't published something at this tag yet. -#if we have we fail the build and stop the pipeline, if we haven't we allow the pipeline to run. -phases: - install: - commands: - - sudo apt-get update -y - - sudo apt-get install python3 python3-pip -y - - pip3 install --upgrade setuptools - pre_build: - commands: - build: - commands: - - echo Build started on `date` - - cd aws-iot-device-sdk-python-v2 - - bash ./continuous-delivery/test_version_exists - post_build: - commands: - - echo Build completed on `date` - diff --git a/utils/publish-release.sh b/utils/publish-release.sh new file mode 100755 index 00000000..242f288b --- /dev/null +++ b/utils/publish-release.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +# Redirect output to stderr. +exec 1>&2 + +RELEASE_TYPE="$1" +RELEASE_TITLE="$2" + +# Make sure there are ONLY two arguments +if [ "$#" != "2" ]; then + echo "ERROR: Arguments passed is NOT equal to two!" + exit 1 +fi + +pushd $(dirname $0) > /dev/null + +# Get the current version +git checkout main +current_version=$(git describe --tags --abbrev=0) +current_version_without_v=$(echo ${current_version} | cut -f2 -dv) + +echo "Current release version is ${current_version_without_v}" + +# Validate that RELEASE_TYPE is what we expect and bump the version +new_version=$(python3 ./update_semantic_version.py --version "${current_version_without_v}" --type "${RELEASE_TYPE}") +if [ "$new_version" == "0.0.0" ]; then + echo "ERROR: Unknown release type! Exitting..." + exit -1 +fi +echo "New version is ${new_version}" + +# Validate that the title is set +if [ "$RELEASE_TITLE" == "" ]; then + echo "ERROR: No title set! Cannot make release. Exitting..." + exit -1 +fi + +# Setup Github credentials +git config --local user.email "aws-sdk-common-runtime@amazon.com" +git config --local user.name "GitHub Actions" + +# --==-- +new_version_branch=AutoTag-v${new_version} +git checkout -b ${new_version_branch} + +# Update the version in the README to show the latest +sed -i -r "s/.*Latest released version:.*/Latest released version: v${new_version}/" ../README.md +git add ../README.md +# Make the commit +git commit -m "[v$new_version] $RELEASE_TITLE" + +# # push the commit and create a PR +git push -u "https://${GITHUB_ACTOR}:${GH_TOKEN}@github.com/aws/aws-iot-device-sdk-python-v2.git" ${new_version_branch} +gh pr create --title "AutoTag PR for v${new_version}" --body "AutoTag PR for v${new_version}" --head ${new_version_branch} + +# # Merge the PR +gh pr merge --admin --squash +# --==-- + +# Update local state with the merged pr (if one was made) and just generally make sure we're up to date +git fetch +git checkout main +git pull "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/aws/aws-iot-device-sdk-python-v2.git" main + +# Create new tag on latest commit with the release title +git tag -f v${new_version} -m "${RELEASE_TITLE}" +# Push new tag to github +git push "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/aws/aws-iot-device-sdk-python-v2.git" --tags + +# Determine if this is a pre-release or not based on the major version +IS_PRE_RELEASE="false" +VERSION_STRING_DELIMITER=. +VERSION_STRING_ARRAY=($(echo "$new_version" | tr $VERSION_STRING_DELIMITER '\n')) +if [ "${VERSION_STRING_ARRAY[0]}" == "0" ]; then + IS_PRE_RELEASE="true" +else + IS_PRE_RELEASE="false" +fi + +# Create the release with auto-generated notes as the description +# - NOTE: This will only add notes if there is at least one PR. If there is no PRs, +# - then this will be blank and need manual input/changing after running. +if [ $IS_PRE_RELEASE == "true" ]; then + gh release create "v${new_version}" -p --generate-notes --notes-start-tag "$current_version" --target main -t "${RELEASE_TITLE}" +else + gh release create "v${new_version}" --generate-notes --notes-start-tag "$current_version" --target main -t "${RELEASE_TITLE}" +fi + +popd > /dev/null diff --git a/utils/update_semantic_version.py b/utils/update_semantic_version.py new file mode 100644 index 00000000..ae9729ef --- /dev/null +++ b/utils/update_semantic_version.py @@ -0,0 +1,40 @@ +import argparse +import sys + +# A simple little helper script for increasing the semantic version passed in. +# Used in the CD workflow. + + +def main(): + argument_parser = argparse.ArgumentParser( + description="Get a new semantic version bumped by the passed-in string") + argument_parser.add_argument("--version", metavar="<1.2.3 for example>", + required=True, help="The version string to update") + argument_parser.add_argument("--type", metavar="", + required=True, help="Which version number to bump") + parsed_commands = argument_parser.parse_args() + + version_tuple = parsed_commands.version.split(".") + if len(version_tuple) != 3: + print("0.0.0") # Error + sys.exit(1) + + if "PATCH" in parsed_commands.type: + version_tuple[2] = str(int(version_tuple[2]) + 1) + elif "MINOR" in parsed_commands.type: + version_tuple[1] = str(int(version_tuple[1]) + 1) + version_tuple[2] = "0" + elif "MAJOR" in parsed_commands.type: + version_tuple[0] = str(int(version_tuple[0]) + 1) + version_tuple[1] = "0" + version_tuple[2] = "0" + else: + print("0.0.0") # error + sys.exit(1) + + print(f"{version_tuple[0]}.{version_tuple[1]}.{version_tuple[2]}") + sys.exit(0) + + +if __name__ == "__main__": + main()