Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[changelog skip] Add CNB release scripts #1136

Merged
merged 1 commit into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/scripts/release-workflow-package-push.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail

# This script is an integral part of the release workflow: .github/workflows/release.yml
# It requires the following environment variables to function correctly:
#
# REQUESTED_BUILDPACK_ID - The ID of the buildpack to package and push to the container registry.

while IFS="" read -r -d "" buildpack_toml_path; do
buildpack_id="$(yj -t <"${buildpack_toml_path}" | jq -r .buildpack.id)"
buildpack_version="$(yj -t <"${buildpack_toml_path}" | jq -r .buildpack.version)"
buildpack_docker_repository="$(yj -t <"${buildpack_toml_path}" | jq -r .metadata.release.docker.repository)"
buildpack_path=$(dirname "${buildpack_toml_path}")
buildpack_build_path="${buildpack_path}"

if [[ $buildpack_id == "${REQUESTED_BUILDPACK_ID}" ]]; then
# Some buildpacks require a build step before packaging. If we detect a build.sh script, we execute it and
# modify the buildpack_build_path variable to point to the directory with the built buildpack instead.
if [[ -f "${buildpack_path}/build.sh" ]]; then
echo "Buildpack has build script, executing..."
"${buildpack_path}/build.sh"
echo "Build finished!"

buildpack_build_path="${buildpack_path}/target"
fi

image_name="${buildpack_docker_repository}:${buildpack_version}"
pack package-buildpack --config "${buildpack_build_path}/package.toml" --publish "${image_name}"

# We might have local changes after building and/or shimming the buildpack. To ensure scripts down the pipeline
# work with a clean state, we reset all local changes here.
git reset --hard
git clean -fdx

echo "::set-output name=id::${buildpack_id}"
echo "::set-output name=version::${buildpack_version}"
echo "::set-output name=path::${buildpack_path}"
echo "::set-output name=address::${buildpack_docker_repository}@$(crane digest "${image_name}")"
exit 0
fi
done < <(find . -name buildpack.toml -print0)

echo "Could not find requested buildpack with id ${REQUESTED_BUILDPACK_ID}!"
exit 1
94 changes: 94 additions & 0 deletions .github/scripts/release-workflow-prepare-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env bash
set -euo pipefail

released_buildpack_id="${1:?}"
released_buildpack_version="${2:?}"
released_buildpack_image_address="${3:?}"

released_buildpack_next_version=$(
echo "${released_buildpack_version}" | awk -F. -v OFS=. '{ $NF=sprintf("%d\n", ($NF+1)); printf $0 }'
)

function escape_for_sed() {
echo "${1:?}" | sed 's/[]\/\[\.]/\\&/g'
}

function is_meta_buildpack_with_dependency() {
local -r buildpack_toml_path="${1:?}"
local -r buildpack_id="${2:?}"

yj -t <"${buildpack_toml_path}" | jq -e "[.order[]?.group[]?.id | select(. == \"${buildpack_id}\")] | length > 0" >/dev/null
}

function package_toml_contains_image_address_root() {
local -r package_toml_path="${1:?}"
local -r image_address_root="${2:?}"

yj -t <"${package_toml_path}" | jq -e "[.dependencies[].uri | select(startswith(\"${image_address_root}\"))] | length > 0" >/dev/null
}

# This is the heading we're looking for when updating CHANGELOG.md files
unreleased_heading=$(escape_for_sed "## [Unreleased]")

while IFS="" read -r -d "" buildpack_toml_path; do
buildpack_id="$(yj -t <"${buildpack_toml_path}" | jq -r .buildpack.id)"
buildpack_path="$(dirname "${buildpack_toml_path}")"
buildpack_package_toml_path="${buildpack_path}/package.toml"
buildpack_changelog_path="${buildpack_path}/CHANGELOG.md"

jq_filter="."

# Update the released buildpack itself
if [[ "${buildpack_id}" == "${released_buildpack_id}" ]]; then
if [[ -f "${buildpack_changelog_path}" ]]; then
new_version_heading=$(escape_for_sed "## [${released_buildpack_version}] $(date +%Y/%m/%d)")
sed -i "s/${unreleased_heading}/${unreleased_heading}\n\n${new_version_heading}/" "${buildpack_changelog_path}"
fi

jq_filter=".buildpack.version = \"${released_buildpack_next_version}\""

# Update meta-buildpacks that have the released buildpack as a dependency
elif is_meta_buildpack_with_dependency "${buildpack_toml_path}" "${released_buildpack_id}"; then
# There are two cases of meta-buildpacks that reference the released buildpack:
#
# 1. The released buildpack is referenced by a local path. In this case, we need to update the reference to
# the next version, not the released version.
# 2. The released buildpack is referenced by a Docker address. In this case, we need to update the reference
# to the released version instead.
target_version_for_meta_buildpack="${released_buildpack_next_version}"

released_buildpack_image_address_root="${released_buildpack_image_address%@*}"
if package_toml_contains_image_address_root "${buildpack_package_toml_path}" "${released_buildpack_image_address_root}"; then
target_version_for_meta_buildpack="${released_buildpack_version}"

package_toml_filter=".dependencies[].uri |= if startswith(\"${released_buildpack_image_address_root}\") then \"${released_buildpack_image_address}\" else . end"
updated_package_toml=$(yj -t <"${buildpack_package_toml_path}" | jq "${package_toml_filter}" | yj -jt)
echo "${updated_package_toml}" >"${buildpack_package_toml_path}"
fi

if [[ -f "${buildpack_changelog_path}" ]]; then
upgrade_entry=$(
escape_for_sed "* Upgraded \`${released_buildpack_id}\` to \`${target_version_for_meta_buildpack}\`"
)

sed -i "s/${unreleased_heading}/${unreleased_heading}\n${upgrade_entry}/" "${buildpack_changelog_path}"
fi

jq_filter=$(
cat <<-EOF
.order |= map(.group |= map(
if .id == "${released_buildpack_id}" then
.version |= "${target_version_for_meta_buildpack}"
else
.
end
))
EOF
)
fi

# Write the filtered buildpack.toml to disk...
updated=$(yj -t <"${buildpack_toml_path}" | jq "${jq_filter}" | yj -jt)
echo "${updated}" >"${buildpack_toml_path}"

done < <(find . -name buildpack.toml -print0)
69 changes: 69 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Release Buildpack
on:
workflow_dispatch:
inputs:
requested_buildpack_id:
description: "Buildpack ID"
required: true

jobs:
release:
name: Release ${{ github.event.inputs.requested_buildpack_id }}
runs-on: ubuntu-20.04 # ubuntu-latest currently resolves to 18.04 which does not have aws-cli 2.x yet
env:
REQUESTED_BUILDPACK_ID: ${{ github.event.inputs.requested_buildpack_id }}
steps:
- id: checkout
name: "Checkout code"
uses: actions/checkout@v2
- id: setup-pack
name: "Setup pack"
uses: buildpacks/github-actions/setup-pack@v4.0.0
- id: login
name: "Login to public ECR"
uses: docker/login-action@v1
with:
registry: public.ecr.aws
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
env:
AWS_REGION: us-east-1
- id: package
name: "Package buildpack and publish to container registry"
run: ./.github/scripts/release-workflow-package-push.sh
shell: bash
- id: add-registry-entry
name: "Request Registry Entry"
uses: docker://ghcr.io/buildpacks/actions/registry/request-add-entry:4.0.0
with:
token: ${{ secrets.PUBLIC_REPO_TOKEN }}
id: ${{ steps.package.outputs.id }}
version: ${{ steps.package.outputs.version }}
address: ${{ steps.package.outputs.address }}
- id: create_release
name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.package.outputs.id }}_${{ steps.package.outputs.version }}
release_name: ${{ steps.package.outputs.id }} ${{ steps.package.outputs.version }}
body: |
Find the changelog here: [CHANGELOG](${{ steps.package.outputs.path }}/CHANGELOG.md)
Docker: `docker pull ${{ steps.package.outputs.address }}`
draft: false
prerelease: false
- id: prepare-pr
name: "Prepare PR with version bumps and CHANGELOG updates"
run: ./.github/scripts/release-workflow-prepare-pr.sh "${{ steps.package.outputs.id }}" "${{ steps.package.outputs.version }}" "docker://${{ steps.package.outputs.address }}"
shell: bash
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
title: "Post-release updates: ${{ steps.package.outputs.id }} ${{ steps.package.outputs.version }}"
commit-message: "Post-release updates: ${{ steps.package.outputs.id }} ${{ steps.package.outputs.version }}"
branch-suffix: "random"
labels: "automation"
body: |
Automated pull-request to update buildpack versions and changelogs
after releasing version `${{ steps.package.outputs.version }}` of `${{ steps.package.outputs.id }}`.
9 changes: 8 additions & 1 deletion buildpack.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ api = "0.2"

[buildpack]
id = "heroku/ruby"
version = "0.0.1"
version = "0.1.0"
name = "Ruby"
ruby_version = "2.6.6"

Expand Down Expand Up @@ -31,3 +31,10 @@ id = "heroku-18"

[[stacks]]
id = "heroku-20"

[metadata]

[metadata.release]

[metadata.release.docker]
repository = "public.ecr.aws/r2f9u0w4/heroku-ruby-buildpack"