From 228224464f2e6602c9c467e038fd7af4cf8c2951 Mon Sep 17 00:00:00 2001 From: "Sean T. Allen" Date: Sun, 10 Nov 2019 03:06:32 -0500 Subject: [PATCH] Add automated release process Adds our standard GitHub based automated release process and associated scripts. Includes - removal of CircleCI - nightly releases to Cloudsmith - tagged releases to Cloudsmith - "latest" tag Docker images to DockerHub - "release" and "X.Y.Z" tag Docker images to DockerHub - changelog-bot support - PR CI workflow - Release process instructions Closes #41 --- .ci-scripts/release/announce-a-release.bash | 174 ++++++++++++++++++ .../build-docker-images-on-release.bash | 62 +++++++ .../release/build-latest-docker-images.bash | 38 ++++ .ci-scripts/release/config.bash | 4 + .ci-scripts/release/start-a-release.bash | 122 ++++++++++++ .../release/trigger-release-announcement.bash | 70 +++++++ .ci-scripts/release/x86-64-unknown-linux.bash | 110 +++++++++++ .ci-scripts/x86-64-unknown-linux-nightly.bash | 56 ------ .circleci/config.yml | 72 -------- .github/workflows/announce-a-release.yml | 19 ++ .../breakage-against-ponyc-latest.yml | 16 ++ .github/workflows/changelog-bot.yml | 18 ++ .github/workflows/latest-docker-image.yml | 20 ++ .github/workflows/nightlies.yml | 20 ++ .github/workflows/pr.yml | 32 ++++ .github/workflows/release.yml | 46 +++++ .github/workflows/start-a-release.yml | 18 ++ Dockerfile | 20 ++ RELEASE_PROCESS.md | 41 +++++ 19 files changed, 830 insertions(+), 128 deletions(-) create mode 100644 .ci-scripts/release/announce-a-release.bash create mode 100644 .ci-scripts/release/build-docker-images-on-release.bash create mode 100644 .ci-scripts/release/build-latest-docker-images.bash create mode 100644 .ci-scripts/release/config.bash create mode 100644 .ci-scripts/release/start-a-release.bash create mode 100644 .ci-scripts/release/trigger-release-announcement.bash create mode 100755 .ci-scripts/release/x86-64-unknown-linux.bash delete mode 100644 .ci-scripts/x86-64-unknown-linux-nightly.bash delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/announce-a-release.yml create mode 100644 .github/workflows/breakage-against-ponyc-latest.yml create mode 100644 .github/workflows/changelog-bot.yml create mode 100644 .github/workflows/latest-docker-image.yml create mode 100644 .github/workflows/nightlies.yml create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/start-a-release.yml create mode 100644 Dockerfile create mode 100644 RELEASE_PROCESS.md diff --git a/.ci-scripts/release/announce-a-release.bash b/.ci-scripts/release/announce-a-release.bash new file mode 100644 index 00000000..cc384863 --- /dev/null +++ b/.ci-scripts/release/announce-a-release.bash @@ -0,0 +1,174 @@ +#!/bin/bash + +# Announces a release after artifacts have been built: +# +# - Publishes release notes to GitHub +# - Announces in the #announce stream of Zulip +# - Adds a note about the release to LWIP +# +# Tools required in the environment that runs this: +# +# - bash +# - changelog-tool +# - curl +# - git +# - jq + +set -o errexit + +# Pull in shared configuration specific to this repo +base=$(dirname "$0") +source "${base}/config.bash" + +# Verify ENV is set up correctly +# We validate all that need to be set in case, in an absolute emergency, +# we need to run this by hand. Otherwise the GitHub actions environment should +# provide all of these if properly configured +if [[ -z "${APPLICATION_NAME}" ]]; then + echo -e "\e[31mName of the application being announced needs to be set in APPLICATION_NAME." + echo -e "Exiting.\e[0m" + exit 1 +fi + +if [[ -z "${RELEASE_TOKEN}" ]]; then + echo -e "\e[31mA personal access token needs to be set in RELEASE_TOKEN." + echo -e "\e[31mIt should not be secrets.GITHUB_TOKEN. It has to be a" + echo -e "\e[31mpersonal access token otherwise next steps in the release" + echo -e "\e[31mprocess WILL NOT trigger." + echo -e "\e[31mPersonal access tokens are in the form:" + echo -e "\e[31m USERNAME:TOKEN" + echo -e "\e[31mfor example:" + echo -e "\e[31m ponylang-main:1234567890" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REF}" ]]; then + echo -e "\e[31mThe release tag needs to be set in GITHUB_REF." + echo -e "\e[31mThe tag should be in the following GitHub specific form:" + echo -e "\e[31m /refs/tags/announce-X.Y.Z" + echo -e "\e[31mwhere X.Y.Z is the version we are announcing" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REPOSITORY}" ]]; then + echo -e "\e[31mName of this repository needs to be set in GITHUB_REPOSITORY." + echo -e "\e[31mShould be in the form OWNER/REPO, for example:" + echo -e "\e[31m ponylang/ponyup" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${ZULIP_TOKEN}" ]]; then + echo -e "\e[31mA Zulip access token needs to be set in ZULIP_TOKEN." + echo -e "Exiting.\e[0m" + exit 1 +fi + +# no unset variables allowed from here on out +# allow above so we can display nice error messages for expected unset variables +set -o nounset + +# Set up .netrc file with GitHub credentials +git config --global user.name 'Ponylang Main Bot' +git config --global user.email 'ponylang.main@gmail.com' +git config --global push.default simple + +PUSH_TO="https://${RELEASE_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + +# Extract version from tag reference +# Tag ref version: "refs/tags/announce-1.0.0" +# Version: "1.0.0" +VERSION="${GITHUB_REF/refs\/tags\/announce-/}" + +# Prepare release notes +echo -e "\e[34mPreparing to update GitHub release notes...\e[0m" +body=$(changelog-tool get "${VERSION}") + +jsontemplate=" +{ + \"tag_name\":\$version, + \"name\":\$version, + \"body\":\$body +} +" + +json=$(jq -n \ +--arg version "$VERSION" \ +--arg body "$body" \ +"${jsontemplate}") + +# Upload release notes +echo -e "\e[34mUploading release notes...\e[0m" +result=$(curl -s -X POST "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -u "${RELEASE_TOKEN}" \ + --data "${json}") + +rslt_scan=$(echo "${result}" | jq -r '.id') +if [ "$rslt_scan" != null ]; then + echo -e "\e[34mRelease notes uploaded\e[0m" +else + echo -e "\e[31mUnable to upload release notes, here's the curl output..." + echo -e "\e[31m${result}\e[0m" + exit 1 +fi + +# Send announcement to Zulip +message=" +Version ${VERSION} of ${APPLICATION_NAME} has been released. + +See the [release notes](https://github.com/${GITHUB_REPOSITORY}/releases/tag/${VERSION}) for more details. +" + +curl -s -X POST https://ponylang.zulipchat.com/api/v1/messages \ + -u ${ZULIP_TOKEN} \ + -d "type=stream" \ + -d "to=announce" \ + -d "topic=${APPLICATION_NAME}" \ + -d "content=${message}" + +# Update Last Week in Pony +echo -e "\e[34mAdding release to Last Week in Pony...\e[0m" + +result=$(curl https://api.github.com/repos/ponylang/ponylang-website/issues?labels=last-week-in-pony) + +lwip_url=$(echo "${result}" | jq -r '.[].url') +if [ "$lwip_url" != "" ]; then + body=" +Version ${VERSION} of ${APPLICATION_NAME} has been released. + +See the [release notes](https://github.com/${GITHUB_REPOSITORY}/releases/tag/${VERSION}) for more details. +" + + jsontemplate=" + { + \"body\":\$body + } + " + + json=$(jq -n \ + --arg body "$body" \ + "${jsontemplate}") + + result=$(curl -s -X POST "$lwip_url/comments" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -u "${RELEASE_TOKEN}" \ + --data "${json}") + + rslt_scan=$(echo "${result}" | jq -r '.id') + if [ "$rslt_scan" != null ]; then + echo -e "\e[34mRelease notice posted to LWIP\e[0m" + else + echo -e "\e[31mUnable to post to LWIP, here's the curl output..." + echo -e "\e[31m${result}\e[0m" + fi +else + echo -e "\e[31mUnable to post to Last Week in Pony." + echo -e "Can't find the issue.\e[0m" +fi + +# delete announce-VERSION tag +echo -e "\e[34mDeleting no longer needed remote tag announce-${VERSION}\e[0m" +git push --delete ${PUSH_TO} "announce-${VERSION}" diff --git a/.ci-scripts/release/build-docker-images-on-release.bash b/.ci-scripts/release/build-docker-images-on-release.bash new file mode 100644 index 00000000..19759002 --- /dev/null +++ b/.ci-scripts/release/build-docker-images-on-release.bash @@ -0,0 +1,62 @@ +#!/bin/bash + +# *** You should already be logged in to DockerHub when you run this *** +# +# Builds docker release images with two tags: +# +# - release +# - X.Y.Z for example 0.32.1 +# +# Tools required in the environment that runs this: +# +# - bash +# - docker + +set -o errexit + +# Pull in shared configuration specific to this repo +base=$(dirname "$0") +source "${base}/config.bash" + +# Verify ENV is set up correctly +# We validate all that need to be set in case, in an absolute emergency, +# we need to run this by hand. Otherwise the GitHub actions environment should +# provide all of these if properly configured +if [[ -z "${GITHUB_REF}" ]]; then + echo -e "\e[31mThe release tag needs to be set in GITHUB_REF." + echo -e "\e[31mThe tag should be in the following GitHub specific form:" + echo -e "\e[31m /refs/tags/X.Y.Z" + echo -e "\e[31mwhere X.Y.Z is the version we are releasing" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REPOSITORY}" ]]; then + echo -e "\e[31mName of this repository needs to be set in GITHUB_REPOSITORY." + echo -e "\e[31mShould be in the form OWNER/REPO, for example:" + echo -e "\e[31m ponylang/ponyup" + echo -e "\e[31mThis will be used as the docker image name." + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +# no unset variables allowed from here on out +# allow above so we can display nice error messages for expected unset variables +set -o nounset + +# We aren't validating TAG is in our x.y.z format but we could. +# For now, TAG validating is left up to the configuration in +# our GitHub workflow +# Tag ref version: "refs/tags/1.0.0" +# Version: "1.0.0" +VERSION="${GITHUB_REF/refs\/tags\//}" + +# Build and push :VERSION tag e.g. ponylang/ponyup:0.32.1 +DOCKER_TAG=${GITHUB_REPOSITORY}:"${VERSION}" +docker build -t "${DOCKER_TAG}" . +docker push "${DOCKER_TAG}" + +# Build and push "release" tag e.g. ponylang/ponyup:release +DOCKER_TAG=${GITHUB_REPOSITORY}:release +docker build -t "${DOCKER_TAG}" . +docker push "${DOCKER_TAG}" diff --git a/.ci-scripts/release/build-latest-docker-images.bash b/.ci-scripts/release/build-latest-docker-images.bash new file mode 100644 index 00000000..52c39bac --- /dev/null +++ b/.ci-scripts/release/build-latest-docker-images.bash @@ -0,0 +1,38 @@ +#!/bin/bash + +# *** You should already be logged in to DockerHub when you run this *** +# +# Builds docker latest docker images. +# +# Tools required in the environment that runs this: +# +# - bash +# - docker + +set -o errexit + +# Pull in shared configuration specific to this repo +base=$(dirname "$0") +source "${base}/config.bash" + +# Verify ENV is set up correctly +# We validate all that need to be set in case, in an absolute emergency, +# we need to run this by hand. Otherwise the GitHub actions environment should +# provide all of these if properly configured +if [[ -z "${GITHUB_REPOSITORY}" ]]; then + echo -e "\e[31mName of this repository needs to be set in GITHUB_REPOSITORY." + echo -e "\e[31mShould be in the form OWNER/REPO, for example:" + echo -e "\e[31m ponylang/ponyup" + echo -e "\e[31mThis will be used as the docker image name." + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +# no unset variables allowed from here on out +# allow above so we can display nice error messages for expected unset variables +set -o nounset + +# Build and push "latest" tag e.g. ponylang/ponyup:latest +DOCKER_TAG=${GITHUB_REPOSITORY}:latest +docker build -t "${DOCKER_TAG}" . +docker push "${DOCKER_TAG}" diff --git a/.ci-scripts/release/config.bash b/.ci-scripts/release/config.bash new file mode 100644 index 00000000..18112662 --- /dev/null +++ b/.ci-scripts/release/config.bash @@ -0,0 +1,4 @@ +#!/bin/bash + +export APPLICATION_NAME="corral" +export APPLICATION_SUMMARY="Pony dependency manager tool" diff --git a/.ci-scripts/release/start-a-release.bash b/.ci-scripts/release/start-a-release.bash new file mode 100644 index 00000000..b0f4fb20 --- /dev/null +++ b/.ci-scripts/release/start-a-release.bash @@ -0,0 +1,122 @@ +#!/bin/bash + +# Starts the release process by: +# +# - Getting latest changes on master +# - Updating version in +# - VERSION +# - CHANGELOG.md +# - Pushing updated VERSION and CHANGELOG.md back to master +# - Pushing tag to kick off building artifacts +# - Adding a new "unreleased" section to CHANGELOG +# - Pushing updated CHANGELOG back to master +# +# Tools required in the environment that runs this: +# +# - bash +# - changelog-tool +# - git + +set -o errexit + +# Pull in shared configuration specific to this repo +base=$(dirname "$0") +source "${base}/config.bash" + +# Verify ENV is set up correctly +# We validate all that need to be set in case, in an absolute emergency, +# we need to run this by hand. Otherwise the GitHub actions environment should +# provide all of these if properly configured +if [[ -z "${RELEASE_TOKEN}" ]]; then + echo -e "\e[31mA personal access token needs to be set in RELEASE_TOKEN." + echo -e "\e[31mIt should not be secrets.GITHUB_TOKEN. It has to be a" + echo -e "\e[31mpersonal access token otherwise next steps in the release" + echo -e "\e[31mprocess WILL NOT trigger." + echo -e "\e[31mPersonal access tokens are in the form:" + echo -e "\e[31m USERNAME:TOKEN" + echo -e "\e[31mfor example:" + echo -e "\e[31m ponylang-main:1234567890" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REF}" ]]; then + echo -e "\e[31mThe release tag needs to be set in GITHUB_REF." + echo -e "\e[31mThe tag should be in the following GitHub specific form:" + echo -e "\e[31m /refs/tags/release-X.Y.Z" + echo -e "\e[31mwhere X.Y.Z is the version we are releasing" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REPOSITORY}" ]]; then + echo -e "\e[31mName of this repository needs to be set in GITHUB_REPOSITORY." + echo -e "\e[31mShould be in the form OWNER/REPO, for example:" + echo -e "\e[31m ponylang/ponyup" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +# no unset variables allowed from here on out +# allow above so we can display nice error messages for expected unset variables +set -o nounset + +# Set up .netrc file with GitHub credentials +git config --global user.name 'Ponylang Main Bot' +git config --global user.email 'ponylang.main@gmail.com' +git config --global push.default simple + +PUSH_TO="https://${RELEASE_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + +# Extract version from tag reference +# Tag ref version: "refs/tags/release-1.0.0" +# Version: "1.0.0" +VERSION="${GITHUB_REF/refs\/tags\/release-/}" + +### this doesn't account for master changing commit, assumes we are HEAD +# or can otherwise push without issue. that shouldl error out without issue. +# leaving us to restart from a different HEAD commit +git checkout master +git pull + +# update VERSION +echo -e "\e[34mUpdating VERSION to ${VERSION}\e[0m" +echo "${VERSION}" > VERSION + +# version the changelog +echo -e "\e[34mUpdating CHANGELOG.md for release\e[0m" +changelog-tool release "${VERSION}" -e + +# commit CHANGELOG and VERSION updates +echo -e "\e[34mCommiting VERSION and CHANGELOG.md changes\e[0m" +git add CHANGELOG.md VERSION +git commit -m "${VERSION} release" + +# tag release +echo -e "\e[34mTagging for release to kick off building artifacts\e[0m" +git tag "${VERSION}" + +# push to release to remote +echo -e "\e[34mPushing commited changes back to master\e[0m" +git push ${PUSH_TO} master +echo -e "\e[34mPushing ${VERSION} tag\e[0m" +git push ${PUSH_TO} "${VERSION}" + +# pull again, just in case, odds of this being needed are really slim +git pull + +# update CHANGELOG for new entries +echo -e "\e[34mAdding new 'unreleased' section to CHANGELOG.md\e[0m" +changelog-tool unreleased -e + +# commit changelog and push to master +echo -e "\e[34mCommiting CHANGELOG.md change\e[0m" +git add CHANGELOG.md +git commit -m "Add unreleased section to CHANGELOG post ${VERSION} release [skip ci]" + +echo -e "\e[34mPushing CHANGELOG.md\e[0m" +git push ${PUSH_TO} master + +# delete release-VERSION tag +echo -e "\e[34mDeleting no longer needed remote tag release-${VERSION}\e[0m" +git push --delete ${PUSH_TO} "release-${VERSION}" diff --git a/.ci-scripts/release/trigger-release-announcement.bash b/.ci-scripts/release/trigger-release-announcement.bash new file mode 100644 index 00000000..0045612f --- /dev/null +++ b/.ci-scripts/release/trigger-release-announcement.bash @@ -0,0 +1,70 @@ +#!/bin/bash + +# Triggers the running of the announce a release process +# +# - Creates announce-X.Y.Z tag and pushes to remote repo +# +# This script should be set up in CI to only run after all build artifact +# creation tasks have successfully run. It is built to be a separate script +# and ci step so that multi-artifacts could in theory be created and uploaded +# before a release is announced. +# +# Tools required in the environment that runs this: +# +# - bash +# - git + +set -o errexit + +# Pull in shared configuration specific to this repo +base=$(dirname "$0") +source "${base}/config.bash" + +# Verify ENV is set up correctly +# We validate all that need to be set in case, in an absolute emergency, +# we need to run this by hand. Otherwise the GitHub actions environment should +# provide all of these if properly configured +if [[ -z "${RELEASE_TOKEN}" ]]; then + echo -e "\e[31mA personal access token needs to be set in RELEASE_TOKEN." + echo -e "\e[31mIt should not be secrets.GITHUB_TOKEN. It has to be a" + echo -e "\e[31mpersonal access token otherwise next steps in the release" + echo -e "\e[31mprocess WILL NOT trigger." + echo -e "\e[31mPersonal access tokens are in the form:" + echo -e "\e[31m USERNAME:TOKEN" + echo -e "\e[31mfor example:" + echo -e "\e[31m ponylang-main:1234567890" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REF}" ]]; then + echo -e "\e[31mA tag for the version we are announcing needs to be set in GITHUB_REF." + echo -e "\e[31mThe tag should be in the following GitHub specific form:" + echo -e "\e[31m /refs/tags/X.Y.Z" + echo -e "\e[31mwhere X.Y.Z is the version we are announcing" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +# no unset variables allowed from here on out +# allow above so we can display nice error messages for expected unset variables +set -o nounset + +git config --global user.name 'Ponylang Main Bot' +git config --global user.email 'ponylang.main@gmail.com' +git config --global push.default simple + +PUSH_TO="https://${RELEASE_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + +# Extract version from tag reference +# Tag ref version: "refs/tags/1.0.0" +# Version: "1.0.0" +VERSION="${GITHUB_REF/refs\/tags\//}" + +# tag for announcement +echo -e "\e[34mTagging to kick off release announcement\e[0m" +git tag "announce-${VERSION}" + +# push tag +echo -e "\e[34mPushing announce-${VERSION} tag\e[0m" +git push ${PUSH_TO} "announce-${VERSION}" diff --git a/.ci-scripts/release/x86-64-unknown-linux.bash b/.ci-scripts/release/x86-64-unknown-linux.bash new file mode 100755 index 00000000..7e3402f4 --- /dev/null +++ b/.ci-scripts/release/x86-64-unknown-linux.bash @@ -0,0 +1,110 @@ +#!/bin/bash + +# x86-64-unknown-linux release: +# +# - Builds release package +# - Uploads to Cloudsmith +# +# Tools required in the environment that runs this: +# +# - bash +# - cloudsmith-cli +# - GNU gzip +# - GNU make +# - ponyc (musl based version) +# - GNU tar + +set -o errexit + +# Pull in shared configuration specific to this repo +base=$(dirname "$0") +source "${base}/config.bash" + +# Verify ENV is set up correctly +# We validate all that need to be set in case, in an absolute emergency, +# we need to run this by hand. Otherwise the GitHub actions environment should +# provide all of these if properly configured +if [[ -z "${CLOUDSMITH_API_KEY}" ]]; then + echo -e "\e[31mCloudsmith API key needs to be set in CLOUDSMITH_API_KEY." + echo -e "Exiting.\e[0m" + exit 1 +fi + +if [[ -z "${GITHUB_REPOSITORY}" ]]; then + echo -e "\e[31mName of this repository needs to be set in GITHUB_REPOSITORY." + echo -e "\e[31mShould be in the form OWNER/REPO, for example:" + echo -e "\e[31m ponylang/ponyup" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${APPLICATION_NAME}" ]]; then + echo -e "\e[31mAPPLICATION_NAME needs to be set." + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${APPLICATION_SUMMARY}" ]]; then + echo -e "\e[31mAPPLICATION_SUMMARY needs to be set." + echo -e "\e[31mIt's a short description of the application that will appear in Cloudsmith." + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +if [[ -z "${CLOUDSMITH_REPO}" ]]; then + echo -e "\e[31mCLOUDSMITH_REPO needs to be set." + echo -e "\e[31mShould be one of:" + echo -e "\e[35m nightlies" + echo -e "\e[35m releases" + echo -e "\e[31mExiting.\e[0m" + exit 1 +fi + +# no unset variables allowed from here on out +# allow above so we can display nice error messages for expected unset variables +set -o nounset + +TODAY=$(date +%Y%m%d) + +# Compiler target parameters +ARCH=x86-64 + +# Triple construction +VENDOR=unknown +OS=linux +TRIPLE=${ARCH}-${VENDOR}-${OS} + +# Build parameters +BUILD_PREFIX=$(mktemp -d) +APPLICATION_VERSION="nightly-${TODAY}" +BUILD_DIR=${BUILD_PREFIX}/${APPLICATION_VERSION} + +# Asset information +PACKAGE_DIR=$(mktemp -d) +PACKAGE=${APPLICATION_NAME}-${TRIPLE} + +# Cloudsmith configuration +CLOUDSMITH_VERSION=${TODAY} +ASSET_OWNER=ponylang +ASSET_REPO=${CLOUDSMITH_REPO} +ASSET_PATH=${ASSET_OWNER}/${ASSET_REPO} +ASSET_FILE=${PACKAGE_DIR}/${PACKAGE}.tar.gz +ASSET_SUMMARY="${APPLICATION_SUMMARY}" +ASSET_DESCRIPTION="https://github.com/${GITHUB_REPOSITORY}" + +# Build application installation +echo -e "\e[34mBuilding ${APPLICATION_NAME}...\e[0m" +make install prefix="${BUILD_DIR}" arch=${ARCH} \ + version="${APPLICATION_VERSION}" static=true linker=bfd + +# Package it all up +echo -e "\e[34mCreating .tar.gz of ${APPLICATION_NAME}...\e[0m" +pushd "${BUILD_PREFIX}" || exit 1 +tar -cvzf "${ASSET_FILE}" * +popd || exit 1 + +# Ship it off to cloudsmith +echo -e "\e[34mUploading package to cloudsmith...\e[0m" +cloudsmith push raw --version "${CLOUDSMITH_VERSION}" \ + --api-key "${CLOUDSMITH_API_KEY}" --summary "${ASSET_SUMMARY}" \ + --description "${ASSET_DESCRIPTION}" ${ASSET_PATH} "${ASSET_FILE}" diff --git a/.ci-scripts/x86-64-unknown-linux-nightly.bash b/.ci-scripts/x86-64-unknown-linux-nightly.bash deleted file mode 100644 index 2564c479..00000000 --- a/.ci-scripts/x86-64-unknown-linux-nightly.bash +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -set -e - -API_KEY=$1 -if [[ ${API_KEY} == "" ]] -then - echo "API_KEY needs to be supplied as first script argument." - exit 1 -fi - -TODAY=$(date +%Y%m%d) - -# Compiler target parameters -ARCH=x86-64 - -# Triple construction -VENDOR=unknown -OS=linux -TRIPLE=${ARCH}-${VENDOR}-${OS} - -# Build parameters -BUILD_PREFIX=$(mktemp -d) -CORRAL_VERSION="nightly-${TODAY}" -BUILD_DIR=${BUILD_PREFIX}/${CORRAL_VERSION} - -# Asset information -PACKAGE_DIR=$(mktemp -d) -PACKAGE=corral-${TRIPLE} - -# Cloudsmith configuration -CLOUDSMITH_VERSION=${TODAY} -ASSET_OWNER=ponylang -ASSET_REPO=nightlies -ASSET_PATH=${ASSET_OWNER}/${ASSET_REPO} -ASSET_FILE=${PACKAGE_DIR}/${PACKAGE}.tar.gz -ASSET_SUMMARY="Pony dependency manager" -ASSET_DESCRIPTION="https://github.com/ponylang/corral" - -# Build corral installation -echo "Building corral..." -make install prefix=${BUILD_DIR} arch=${ARCH} version="${CORRAL_VERSION}" \ - static=true linker=bfd - -# Package it all up -echo "Creating .tar.gz of corral..." -pushd ${BUILD_PREFIX} || exit 1 -tar -cvzf ${ASSET_FILE} * -popd || exit 1 - -# Ship it off to cloudsmith -echo "Uploading package to cloudsmith..." -cloudsmith push raw --version "${CLOUDSMITH_VERSION}" --api-key ${API_KEY} \ - --summary "${ASSET_SUMMARY}" --description "${ASSET_DESCRIPTION}" \ - ${ASSET_PATH} ${ASSET_FILE} - diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 0f401d23..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,72 +0,0 @@ -version: 2.1 - -orbs: - zulip: ponylang/zulip@1 - -jobs: - x86-64-unknown-linux-nightly: - docker: - - image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:release - steps: - - run: apk add --update py-pip - - run: pip install cloudsmith-cli - - checkout - - run: bash .ci-scripts/x86-64-unknown-linux-nightly.bash ${CLOUDSMITH_API_KEY} - - zulip/status: - fail_only: true - - vs-ponyc-release: - docker: - - image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:release - steps: - - checkout - - run: make test - - zulip/status: - fail_only: true - - vs-ponyc-master: - docker: - - image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:latest - steps: - - checkout - - run: make test - - zulip/status: - fail_only: true - - verify-changelog: - docker: - - image: ponylang/changelog-tool:release - steps: - - checkout - - run: changelog-tool verify - -workflows: - version: 2 - every-commit: - jobs: - - verify-changelog - - vs-ponyc-release: - context: org-global - - daily-check-for-breakage: - triggers: - - schedule: - cron: "0 3 * * *" - filters: - branches: - only: master - jobs: - - vs-ponyc-master: - context: org-global - - create-and-upload-nightly-release: - triggers: - - schedule: - cron: "0 0 * * *" - filters: - branches: - only: master - jobs: - - x86-64-unknown-linux-nightly: - context: org-global - diff --git a/.github/workflows/announce-a-release.yml b/.github/workflows/announce-a-release.yml new file mode 100644 index 00000000..9bc6b6ba --- /dev/null +++ b/.github/workflows/announce-a-release.yml @@ -0,0 +1,19 @@ +name: Announce a release + +on: + push: + tags: announce-*.*.* + +jobs: + announce-a-release: + name: Announce a release + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-release:20191107 + steps: + - uses: actions/checkout@v1 + - name: Announce + run: bash .ci-scripts/release/announce-a-release.bash + env: + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} + ZULIP_TOKEN: ${{ secrets.ZULIP_TOKEN }} diff --git a/.github/workflows/breakage-against-ponyc-latest.yml b/.github/workflows/breakage-against-ponyc-latest.yml new file mode 100644 index 00000000..402147f3 --- /dev/null +++ b/.github/workflows/breakage-against-ponyc-latest.yml @@ -0,0 +1,16 @@ +name: Nightly breakage against ponyc master + +on: + schedule: + - cron: "0 2 * * *" + +jobs: + vs-ponyc-master: + name: Verify master against ponyc master + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:latest + steps: + - uses: actions/checkout@v1 + - name: Test with against ponyc master + run: make test diff --git a/.github/workflows/changelog-bot.yml b/.github/workflows/changelog-bot.yml new file mode 100644 index 00000000..ac5aec58 --- /dev/null +++ b/.github/workflows/changelog-bot.yml @@ -0,0 +1,18 @@ +name: Changelog Bot + +on: + push: + branches: + - master + paths-ignore: + - CHANGELOG.md + +jobs: + changelog-bot: + runs-on: ubuntu-latest + name: Update CHANGELOG.md + steps: + - name: Update Changelog + uses: ponylang/changelog-bot-action@0.1.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/latest-docker-image.yml b/.github/workflows/latest-docker-image.yml new file mode 100644 index 00000000..406182bf --- /dev/null +++ b/.github/workflows/latest-docker-image.yml @@ -0,0 +1,20 @@ +name: Build latest Docker images + +on: + push: + branches: + - master + +jobs: + build-latest-docker-image: + name: Build and push latest Docker image + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Docker login + run: "docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD" + env: + DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + - name: Build and push + run: bash .ci-scripts/release/build-latest-docker-images.bash diff --git a/.github/workflows/nightlies.yml b/.github/workflows/nightlies.yml new file mode 100644 index 00000000..1cde8bf2 --- /dev/null +++ b/.github/workflows/nightlies.yml @@ -0,0 +1,20 @@ +name: Nightlies + +on: + schedule: + - cron: "0 0 * * *" + +jobs: + x86-64-unknown-linux-nightly: + name: Build and upload x86-64-unknown-linux-nightly to Cloudsmith + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:release + steps: + - uses: actions/checkout@v1 + - name: Build and upload + run: bash .ci-scripts/release/x86-64-unknown-linux.bash + env: + CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} + CLOUDSMITH_REPO: nightlies + diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 00000000..7360f74c --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,32 @@ +name: PR + +on: pull_request + +jobs: + validate-docker-image-builds: + name: Validate Docker image builds + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Docker build + run: "docker build ." + + verify-changelog: + name: Verify CHANGELOG is valid + runs-on: ubuntu-latest + container: + image: ponylang/changelog-tool:release + steps: + - uses: actions/checkout@v1 + - name: Verify CHANGELOG + run: changelog-tool verify + + vs-ponyc-release: + name: Verify PR builds most recent ponyc release + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:release + steps: + - uses: actions/checkout@v1 + - name: Test with most recent ponyc release + run: make test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..7e211a78 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: Release + +on: + push: + tags: + - \d+.\d+.\d+ + +jobs: + create-and-upload-a-release: + name: Build and upload to Cloudsmith + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-x86-64-unknown-linux-builder:release + steps: + - uses: actions/checkout@v1 + - name: Build and upload + run: bash .ci-scripts/release/x86-64-unknown-linux.bash + env: + CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} + CLOUDSMITH_REPO: releases + + build-release-docker-images: + name: Build and push release Docker images + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Docker login + run: "docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD" + env: + DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + - name: Build and push + run: bash .ci-scripts/release/build-docker-images-on-release.bash + + trigger-release-announcement: + name: Trigger release announcement + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-release:20191107 + needs: [create-and-upload-a-release, build-release-docker-images] + steps: + - uses: actions/checkout@v1 + - name: Trigger release announcement + run: bash .ci-scripts/release/trigger-release-announcement.bash + env: + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} diff --git a/.github/workflows/start-a-release.yml b/.github/workflows/start-a-release.yml new file mode 100644 index 00000000..30410a83 --- /dev/null +++ b/.github/workflows/start-a-release.yml @@ -0,0 +1,18 @@ +name: Start a release + +on: + push: + tags: release-*.*.* + +jobs: + start-a-release: + name: Start a release + runs-on: ubuntu-latest + container: + image: ponylang/shared-docker-ci-release:20191107 + steps: + - uses: actions/checkout@v1 + - name: Start release process + run: bash .ci-scripts/release/start-a-release.bash + env: + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..a7d7d0e7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM ponylang/ponyc:release-alpine AS build + +WORKDIR /src/corral + +COPY Makefile LICENSE VERSION /src/corral/ + +WORKDIR /src/corral/corral + +COPY corral /src/corral/corral/ + +WORKDIR /src/corral + +RUN make arch=x86-64 static=true linker=bfd \ + && make install + +FROM alpine:3.10 + +COPY --from=build /usr/local/bin/corral /usr/local/bin/corral + +CMD corral diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md new file mode 100644 index 00000000..93cd1140 --- /dev/null +++ b/RELEASE_PROCESS.md @@ -0,0 +1,41 @@ +# How to cut a release + +This document is aimed at members of the team who might be cutting a release. It serves as a checklist that can take you through doing a release step-by-step. + +## Prerequisites + +* You must have commit access to the this repository. +* It would be helpful to have read and write access to the ponylang [cloudsmith](https://cloudsmith.io/) account. + +## Releasing + +Please note that this document was written with the assumption that you are using a clone of this repo. You have to be using a clone rather than a fork. It is advised to your do this by making a fresh clone of the repo from which you will release. + +Before getting started, you will need a number for the version that you will be releasing as well as an agreed upon "golden commit" that will form the basis of the release. + +The "golden commit" must be `HEAD` on the `master` branch of this repository. At this time, releasing from any other location is not supported. + +For the duration of this document, that we are releasing version is `0.3.1`. Any place you see those values, please substitute your own version. + +```bash +git tag release-0.3.1 +git push origin release-0.3.1 +``` + +## If something goes wrong + +The release process can be restarted at various points in it's lifecycle by pushing specially crafted tags. + +## Start a release + +As documented above, a release is started by pushing a tag of the form `release-x.y.z`. + +## Build artifacts + +The release process can be manually restarted from here by pushing a tag of the form `x.y.z`. The pushed tag must be on the commit to build the release artifacts from. During the normal process, that commit is the same as the one that `release-x.y.z`. + +## Announce release + +The release process can be manually restarted from here by push a tag of the form `announce-x.y.z`. The tag must be on a commit that is after "Release x.y.z" commit that was generated during the `Start a release` portion of the process. + +If you need to restart from here, you will need to pull the latest updates from the repo as it will have changed and the commit you need to tag will not be available in your copy of the repo with pulling.