Final migration of release code off of Travis CI. (#12239)

* Initial version of release workflow.

* Remove release code from Travis config.

Final removal of the Travis CI code will be handled separately.

* Do not push changes if not running in GHA.

This simplifies testing the core logic locally.

* Remove remote branch existence checking.

It is not strictly nesescary for the expected execution context, and it
makes it harder to test locally safely.

* Fixed some minor oversights.

* Make git config repo local to make testing easier.
This commit is contained in:
Austin S. Hemmelgarn 2022-03-09 08:30:47 -05:00 committed by GitHub
parent d8aba23d0f
commit 00836aec82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 387 additions and 88 deletions

215
.github/scripts/prepare-changelog.sh vendored Executable file
View File

@ -0,0 +1,215 @@
#!/bin/sh
set -e
REPO="${1}"
EVENT_NAME="${2}"
EVENT_TYPE="${3}"
EVENT_VERSION="${4}"
##############################################################
# Utility functions
generate_changelog() {
echo "::group::Generating changelog"
if [ -n "${1}" ]; then
OPTS="--future-release ${1}"
fi
# shellcheck disable=SC2086
docker run -it -v "$(pwd)":/project markmandel/github-changelog-generator:latest \
--user "netdata" \
--project "netdata" \
--token "${GITHUB_TOKEN}" \
--since-tag "v1.10.0" \
--unreleased-label "**Next release**" \
--no-issues \
--exclude-labels "stale,duplicate,question,invalid,wontfix,discussion,no changelog" \
--max-issues 500 \
--bug-labels IGNOREBUGS ${OPTS}
echo "::endgroup::"
}
commit_changes() {
branch="${1}"
msg="${2}"
tag="${3}"
echo "::group::Committing changelog and version file and pushing changes."
git checkout "${branch}"
git add packaging/version CHANGELOG.md
git commit -m "[ci skip] ${msg}"
if [ -n "${tag}" ]; then
git tag "${tag}"
opts="--tags"
fi
if [ -n "${GITHUB_ACTIONS}" ]; then
git push -u origin ${opts} "${branch}"
else
echo "Not pushing changes as we are not running in GitHub Actions."
echo "Would have pushed ${branch} to origin, with additional options '${opts}'"
fi
echo "::endgroup::"
}
##############################################################
# Version validation functions
check_version_format() {
if ! echo "${EVENT_VERSION}" | grep -qE '^v[[::digit::]]+\.[[::digit::]]+\.[[::digit::]]+$'; then
echo "::error::The supplied version (${EVENT_VERSION}) is not a valid version string."
return 1
fi
}
patch_is_zero() {
if ! echo "${EVENT_VERSION}" | grep -qE '^v[[::digit::]]+\.[[::digit::]]+\.0$'; then
echo "::error::The patch number for a ${EVENT_TYPE} build must be 0."
return 1
fi
}
minor_is_zero() {
if ! echo "${EVENT_VERSION}" | grep -qE '^v[[::digit::]]+\.0'; then
echo "::error::The minor version number for a ${EVENT_TYPE} build must be 0."
return 1
fi
}
major_matches() {
current_major="$(cut -f 1 -d '-' packaging/version | cut -f 1 -d '.' | cut -f 2 -d 'v')"
target_major="$(echo "${EVENT_VERSION}" | cut -f 1 -d '.' | cut -f 2 -d 'v')"
if [ "${target_major}" != "${current_major}" ]; then
echo "::error::Major version mismatch, expected ${current_major} but got ${target_major}."
return 1
fi
}
minor_matches() {
current_minor="$(cut -f 1 -d '-' packaging/version | cut -f 2 -d '.')"
target_minor="$(echo "${EVENT_VERSION}" | cut -f 2 -d '.')"
if [ "${target_minor}" != "${current_minor}" ]; then
echo "::error::Minor version mismatch, expected ${current_minor} but got ${target_minor}."
return 1
fi
}
check_for_existing_tag() {
if git tag | grep -qE "^${EVENT_VERSION}$"; then
echo "::error::A tag for version ${EVENT_VERSION} already exists."
return 1
fi
}
check_newer_major_version() {
current="$(cut -f 1 -d '-' packaging/version | cut -f 1 -d '.' | cut -f 2 -d 'v')"
target="$(echo "${EVENT_VERSION}" | cut -f 1 -d '.' | cut -f 2 -d 'v')"
if [ "${target}" -le "${current}" ]; then
echo "::error::Version ${EVENT_VERSION} is not newer than the current version."
return 1
fi
}
check_newer_minor_version() {
current="$(cut -f 1 -d '-' packaging/version | cut -f 2 -d '.')"
target="$(echo "${EVENT_VERSION}" | cut -f 2 -d '.')"
if [ "${target}" -le "${current}" ]; then
echo "::error::Version ${EVENT_VERSION} is not newer than the current version."
return 1
fi
}
check_newer_patch_version() {
current="$(cut -f 1 -d '-' packaging/version | cut -f 3 -d '.')"
target="$(echo "${EVENT_VERSION}" | cut -f 3 -d '.')"
if [ "${target}" -le "${current}" ]; then
echo "::error::Version ${EVENT_VERSION} is not newer than the current version."
return 1
fi
}
##############################################################
# Core logic
git config user.name "netdatabot"
git config user.email "bot@netdata.cloud"
if [ "${REPO}" != "netdata/netdata" ]; then
echo "::notice::Not running in the netdata/netdata repository, not queueing a release build."
echo "::set-output name=run::false"
elif [ "${EVENT_NAME}" = 'schedule' ] || [ "${EVENT_TYPE}" = 'nightly' ]; then
echo "::notice::Preparing a nightly release build."
LAST_TAG=$(git describe --abbrev=0 --tags)
COMMITS_SINCE_RELEASE=$(git rev-list "${LAST_TAG}"..HEAD --count)
NEW_VERSION="${LAST_TAG}-$((COMMITS_SINCE_RELEASE + 1))-nightly"
generate_changelog "" || exit 1
echo "${NEW_VERSION}" > packaging/version || exit 1
commit_changes master "Update changelog and version for nightly build: ${NEW_VERSION}."
echo "::set-output name=run::true"
echo "::set-output name=ref::master"
elif [ "${EVENT_TYPE}" = 'patch' ] && [ "${EVENT_VERSION}" != "nightly" ]; then
echo "::notice::Preparing a patch release build."
check_version_format || exit 1
check_for_existing_tag || exit 1
branch_name="$(echo "${EVENT_VERSION}" | cut -f 1-2 -d '.')"
if [ -z "$(git branch --list "${branch_name}")" ]; then
echo "::error::Could not find a branch for the ${branch_name}.x release series."
exit 1
fi
git checkout "${branch_name}"
minor_matches || exit 1
major_matches || exit 1
check_newer_patch_number || exit 1
generate_changelog "${EVENT_VERSION}" || exit 1
echo "${EVENT_VERSION}" > packaging/version || exit 1
commit_changes "${branch_name}" "Patch release ${EVENT_VERSION}." "${EVENT_VERSION}" || exit 1
echo "::set-output name=run::true"
echo "::set-output name=ref::${EVENT_VERSION}"
elif [ "${EVENT_TYPE}" = 'minor' ] && [ "${EVENT_VERSION}" != "nightly" ]; then
echo "::notice::Preparing a minor release build."
check_version_format || exit 1
patch_is_zero || exit 1
major_matches || exit 1
check_newer_minor_version || exit 1
check_for_existing_tag || exit 1
branch_name="$(echo "${EVENT_VERSION}" | cut -f 1-2 -d '.')"
if [ -n "$(git branch --list "${branch_name}")" ]; then
echo "::error::A branch named ${branch_name} already exists in the repository."
exit 1
fi
git branch "${branch_name}"
git checkout "${branch_name}"
generate_changelog "${EVENT_VERSION}" || exit 1
echo "${EVENT_VERSION}" > packaging/version || exit 1
commit_changes "${branch_name}" "Minor release ${EVENT_VERSION}." "${EVENT_VERSION}" || exit 1
echo "::set-output name=run::true"
echo "::set-output name=ref::${EVENT_VERSION}"
elif [ "${EVENT_TYPE}" = 'major' ] && [ "${EVENT_VERSION}" != "nightly" ]; then
echo "::notice::Preparing a major release build."
check_version_format || exit 1
minor_is_zero || exit 1
patch_is_zero || exit 1
check_newer_major_version || exit 1
check_for_existing_tag || exit 1
generate_changelog "${EVENT_VERSION}" || exit 1
echo "${EVENT_VERSION}" > packaging/version || exit 1
commit_changes master "Major release ${EVENT_VERSION}." "${EVENT_VERSION}" || exit 1
echo "::set-output name=run::true"
echo "::set-output name=ref::${EVENT_VERSION}"
else
echo '::error::Unrecognized release type or invalid version.'
exit 1
fi
# shellcheck disable=SC2002
echo "::set-output name=version::$(cat packaging/version | sed 's/^v//' packaging/version)"

View File

@ -17,7 +17,7 @@ on:
default: nightly
required: true
concurrency: # This keeps multiple instances of the job from running concurrently for the same ref and event type.
group: release-${{ github.ref }}-${{ github.event_name }}
group: build-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
build-dist: # Build the distribution tarball and store it as an artifact.

170
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,170 @@
---
# Workflow for triggering a release.
name: Release
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch: # Dispatch runs build and validate, then push to the appropriate storage location.
inputs:
type:
description: Build Type
default: nightly
required: true
version:
description: Version Tag
default: nightly
required: true
concurrency: # This keeps multiple instances of the job from running concurrently for the same ref and event type.
group: release-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
update-changelogs:
name: Update changelog
runs-on: ubuntu-latest
outputs:
ref: ${{ steps.target.outputs.ref }}
version: ${{ steps.target.outputs.version }}
run: ${{ steps.target.outputs.run }}
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
submodules: recursive
- name: Login to DockerHub # Needed to avoid ratelimits in the script we run in the next step.
id: login
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Prepare base ref
id: target
env:
GITHUB_TOKEN: ${{ secrets.NETDATABOT_GITHUB_TOKEN }}
run: >-
.github/scripts/prepare-changelog.sh \
${{ github.repository }} \
${{ github.event_name }} \
${{ github.event.inputs.type }} \
${{ github.event.inputs.version }}
- name: Failure Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_COLOR: 'danger'
SLACK_FOOTER: ''
SLACK_ICON_EMOJI: ':github-actions:'
SLACK_TITLE: 'Failed to prepare changelog:'
SLACK_USERNAME: 'GitHub Actions'
SLACK_MESSAGE: >-
${{ github.repository }}: Failed to prepare changelog.
Checkout: ${{ steps.checkout.outcome }}
Login to DockerHub: ${{ steps.login.outcome }}
Prepare base ref: ${{ steps.target.outcome }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
if: failure()
trigger-artifacts:
name: Trigger artifact builds
runs-on: ubuntu-latest
needs: update-changelogs
if: ${{ needs.update-changelogs.outputs.run }} == 'true'
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v2
with:
ref: ${{ needs.update-changelogs.outputs.ref }}
- name: Trigger build
id: trigger
uses: benc-uk/workflow-dispatch@v1
with:
token: ${{ secrets.NETDATABOT_GITHUB_TOKEN }}
repo: ${{ github.repository }}
workflow: Build
ref: ${{ needs.update-changelogs.outputs.ref }}
inputs: '{"agent_version": "${{ needs.update-changelogs.outputs.version }}", "type": "${{ github.event.inputs.type }}"}'
- name: Failure Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_COLOR: 'danger'
SLACK_FOOTER: ''
SLACK_ICON_EMOJI: ':github-actions:'
SLACK_TITLE: 'Failed to trigger ${{ github.event.inputs.type }} artifact builds:'
SLACK_USERNAME: 'GitHub Actions'
SLACK_MESSAGE: >-
${{ github.repository }}: Failed to trigger ${{ github.event.inputs.type }} artifact builds.
Checkout: ${{ steps.checkout.outcome }}
Trigger build: ${{ steps.trigger.outcome }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
if: failure()
trigger-docker:
name: Trigger docker builds
runs-on: ubuntu-latest
needs: update-changelogs
if: ${{ needs.update-changelogs.outputs.run }} == 'true'
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v2
with:
ref: ${{ needs.update-changelogs.outputs.ref }}
- name: Trigger build
id: trigger
uses: benc-uk/workflow-dispatch@v1
with:
token: ${{ secrets.NETDATABOT_GITHUB_TOKEN }}
repo: ${{ github.repository }}
workflow: Docker
ref: ${{ needs.update-changelogs.outputs.ref }}
inputs: '{"agent_version": "${{ needs.update-changelogs.outputs.version }}"}'
- name: Failure Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_COLOR: 'danger'
SLACK_FOOTER: ''
SLACK_ICON_EMOJI: ':github-actions:'
SLACK_TITLE: 'Failed to trigger ${{ github.event.inputs.type }} Docker builds:'
SLACK_USERNAME: 'GitHub Actions'
SLACK_MESSAGE: >-
${{ github.repository }}: Failed to trigger ${{ github.event.inputs.type }} Docker builds.
Checkout: ${{ steps.checkout.outcome }}
Trigger build: ${{ steps.trigger.outcome }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
if: failure()
trigger-packages:
name: Trigger package builds
runs-on: ubuntu-latest
needs: update-changelogs
if: ${{ needs.update-changelogs.outputs.run }} == 'true'
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v2
with:
ref: ${{ needs.update-changelogs.outputs.ref }}
- name: Trigger build
id: trigger
uses: benc-uk/workflow-dispatch@v1
with:
token: ${{ secrets.NETDATABOT_GITHUB_TOKEN }}
repo: ${{ github.repository }}
workflow: Packages
ref: ${{ needs.update-changelogs.outputs.ref }}
inputs: '{"agent_version": "${{ needs.update-changelogs.outputs.version }}", "type": "${{ github.event.inputs.type }}"}'
- name: Failure Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_COLOR: 'danger'
SLACK_FOOTER: ''
SLACK_ICON_EMOJI: ':github-actions:'
SLACK_TITLE: 'Failed to trigger ${{ github.event.inputs.type }} package builds:'
SLACK_USERNAME: 'GitHub Actions'
SLACK_MESSAGE: >-
${{ github.repository }}: Failed to trigger ${{ github.event.inputs.type }} package builds.
Checkout: ${{ steps.checkout.outcome }}
Trigger build: ${{ steps.trigger.outcome }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
if: failure()

View File

@ -51,26 +51,6 @@ stages:
- name: Build process
if: commit_message =~ /^((?!\[Package (amd64|arm64|i386) (DEB|RPM)( .*)?\]).)*$/
# Nightly operations
- name: Nightly operations
if: branch = master AND type = cron AND env(RUN_NIGHTLY) = yes
- name: Nightly release
if: branch = master AND type = cron AND env(RUN_NIGHTLY) = yes
# Scheduled releases
- name: Support activities on main branch
if: branch = master AND type != pull_request AND type != cron AND repo = netdata/netdata
# We don't run on release candidates
- name: Publish for release
if: >-
branch = master
AND type != pull_request
AND type != cron
AND tag !~ /(-rc)/
AND commit_message =~ /\[netdata (release candidate|(major|minor|patch) release)\]/
# Define stage implementation details
#
@ -86,69 +66,3 @@ jobs:
script: fakeroot ./netdata-installer.sh --install $HOME --dont-wait --dont-start-it --enable-plugin-nfacct --enable-plugin-freeipmi --disable-lto
env: CFLAGS='-O1 -Wall -Wextra -Wformat-signedness -fstack-protector-all -fno-common -DNETDATA_INTERNAL_CHECKS=1 -D_FORTIFY_SOURCE=2 -DNETDATA_VERIFY_LOCKS=1'
after_failure: post_message "TRAVIS_MESSAGE" "<!here> standard netdata build is failing (Still dont know which one, will improve soon)"
- stage: Support activities on main branch
name: Generate changelog for release (only on special and tagged commit msg)
before_script: post_message "TRAVIS_MESSAGE" "Support activities on main branch initiated" "${NOTIF_CHANNEL}"
script:
- echo "GIT Branch:" && git branch
- echo "Last commit:" && git log -1
- echo "GIT Describe:" && git describe
- echo "packaging/version:" && cat packaging/version
- if [[ -z "${GIT_TAG}" ]]; then echo "Running set tag for release" && set_tag_for_release; fi;
- .travis/generate_changelog_and_tag_release.sh
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Changelog generation and tag of release, failed"
git:
depth: false
if: commit_message =~ /\[netdata (release candidate|(major|minor|patch) release)\]/ AND tag !~ /(-rc)/ OR (env(GIT_TAG) IS present AND NOT env(GIT_TAG) IS blank)
# We only publish if a TAG has been set during packaging
- stage: Publish for release
name: Trigger release build and draft release creation
script:
- git checkout "${TRAVIS_BRANCH}" && export BUILD_VERSION="$(cat packaging/version)"
- .travis/trigger_artifact_build.sh "${GITHUB_TOKEN}" "${BUILD_VERSION}" "release"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Failed to trigger release artifact build during nightly release" "${NOTIF_CHANNEL}"
- name: Trigger Docker image build and publish
script:
- git checkout "${TRAVIS_BRANCH}" && export BUILD_VERSION="$(cat packaging/version | cut -d'-' -f1)"
- .travis/trigger_docker_build.sh "${GITHUB_TOKEN}" "${BUILD_VERSION}"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Failed to trigger docker build during release" "${NOTIF_CHANNEL}"
- name: Trigger DEB and RPM package build
script:
- git checkout "${TRAVIS_BRANCH}" && export BUILD_VERSION="$(cat packaging/version | sed 's/^v//' | cut -d'-' -f1)"
- .travis/trigger_package_build.sh "${GITHUB_TOKEN}" "${BUILD_VERSION}" "release"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Failed to trigger deb and rpm package build during release" "${NOTIF_CHANNEL}"
# This is the nightly pre-execution step (Jobs, preparatory steps for nightly, etc)
- stage: Nightly operations
# This is generating the changelog for nightly release and publish it
name: Generate nightly changelog
script:
- ".travis/nightlies.sh"
- ".travis/check_changelog_last_modification.sh"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Nightly changelog generation failed"
git:
depth: false
# This is the nightly execution step
#
- stage: Nightly release
name: Trigger nightly artifact build and upload
script:
- git checkout "${TRAVIS_BRANCH}" && export BUILD_VERSION="$(cat packaging/version)"
- .travis/trigger_artifact_build.sh "${GITHUB_TOKEN}" "${BUILD_VERSION}" "nightly"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Failed to trigger release artifact build during nightly release" "${NOTIF_CHANNEL}"
- name: Trigger Docker image build and publish
script: .travis/trigger_docker_build.sh "${GITHUB_TOKEN}" "nightly"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Failed to trigger docker build during nightly release" "${NOTIF_CHANNEL}"
- name: Trigger DEB and RPM package build
script:
- git checkout "${TRAVIS_BRANCH}" && export BUILD_VERSION="$(cat packaging/version | sed 's/^v//')"
- .travis/trigger_package_build.sh "${GITHUB_TOKEN}" "${BUILD_VERSION}" "nightly"
after_failure: post_message "TRAVIS_MESSAGE" "<!here> Failed to trigger deb and rpm package build during nightly release" "${NOTIF_CHANNEL}"

View File

@ -306,7 +306,7 @@ NETDATA_PREFIX=
LIBS_ARE_HERE=0
NETDATA_ENABLE_ML=""
NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS-}"
RELEASE_CHANNEL="nightly" # check .travis/create_artifacts.sh before modifying
RELEASE_CHANNEL="nightly" # valid values are 'nightly' and 'stable'
IS_NETDATA_STATIC_BINARY="${IS_NETDATA_STATIC_BINARY:-"no"}"
while [ -n "${1}" ]; do
case "${1}" in