Create Release #15435
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Create Release | |
on: | |
schedule: | |
- cron: "*/30 * * * *" # every 30 minutes | |
push: | |
branches: | |
- main | |
workflow_dispatch: | |
inputs: | |
version: | |
description: 'Version of the release to cut (e.g. 1.2.3). No leading v' | |
required: false | |
force: | |
description: 'Release stack even if change validator does not detect changes, or a package is removed' | |
required: true | |
type: choice | |
default: 'false' | |
options: | |
- 'true' | |
- 'false' | |
concurrency: release | |
env: | |
STACKS_FILENAME: "images.json" | |
jobs: | |
preparation: | |
name: Preparation | |
runs-on: ubuntu-22.04 | |
outputs: | |
stacks: ${{ steps.get-stack-names.outputs.stacks }} | |
support_usns: ${{ steps.get-stack-names.outputs.support_usns }} | |
github_repo_name: ${{ steps.repo.outputs.github_repo_name }} | |
registry_repo_name: ${{ steps.repo.outputs.registry_repo_name }} | |
repo_owner: ${{ steps.repo.outputs.repo_owner }} | |
steps: | |
- name: Checkout repo | |
uses: actions/checkout@v4 | |
- name: Get stack names and USN support | |
id: get-stack-names | |
run: | | |
stacks=$( | |
cat <<EOF | |
[ | |
{ | |
"name": "stack", | |
"config_dir": "stack", | |
"output_dir": "build", | |
"build_image": "build", | |
"run_image": "run", | |
"create_build_image": true | |
} | |
] | |
EOF | |
) | |
support_usns=true | |
if [[ -f ${{ env.STACKS_FILENAME }} ]]; then | |
stacks=$(jq '[.images[] | | |
. + | |
{ | |
"create_build_image": (.create_build_image // false) | |
}]' ${{ env.STACKS_FILENAME }} ) | |
support_usns=$( jq '.support_usns' ${{ env.STACKS_FILENAME }} ) | |
fi | |
stacks=$(jq -c <<< "$stacks" ) | |
printf "stacks=%s\n" "${stacks}" >> "$GITHUB_OUTPUT" | |
printf "support_usns=%s\n" "${support_usns}" >> "$GITHUB_OUTPUT" | |
- name: Get Repository Name | |
id: repo | |
run: | | |
full=${{ github.repository }} | |
# Strip off the org and slash from repo name | |
# paketo-buildpacks/jammy-base-stack --> jammy-base-stack | |
repo=$(echo "${full}" | sed 's/^.*\///') | |
echo "github_repo_name=${repo}" >> "$GITHUB_OUTPUT" | |
# Strip off 'stack' suffix from repo name | |
# paketo-buildpacks/jammy-base-stack --> jammy-base | |
registry_repo="${repo//-stack/}" | |
echo "registry_repo_name=${registry_repo}" >> "$GITHUB_OUTPUT" | |
# translates 'paketo-buildpacks' to 'paketobuildpacks' | |
repo_owner="${GITHUB_REPOSITORY_OWNER/-/}" | |
printf "repo_owner=%s\n" "${repo_owner}" >> "$GITHUB_OUTPUT" | |
poll_images: | |
name: Poll Images | |
runs-on: ubuntu-22.04 | |
needs: preparation | |
strategy: | |
matrix: | |
stacks: ${{ fromJSON(needs.preparation.outputs.stacks) }} | |
outputs: | |
images_need_update: ${{ steps.compare_previous_and_current_sha256_hash_codes.outputs.images_need_update }} | |
steps: | |
- name: Find and Download Previous build image hash code of stack ${{ matrix.stacks.build_image }} | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: paketo-buildpacks/github-config/actions/release/find-and-download-asset@main | |
with: | |
asset_pattern: "${{ matrix.stacks.build_image }}.oci.sha256" | |
search_depth: 1 | |
repo: ${{ github.repository }} | |
output_path: "/github/workspace/previous_${{ matrix.stacks.build_image }}.oci.sha256" | |
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} | |
- name: Find and Download Previous run image hash code of stack ${{ matrix.stacks.run_image }} | |
uses: paketo-buildpacks/github-config/actions/release/find-and-download-asset@main | |
with: | |
asset_pattern: "${{ matrix.stacks.run_image }}.oci.sha256" | |
search_depth: 1 | |
repo: ${{ github.repository }} | |
output_path: "/github/workspace/previous_${{ matrix.stacks.run_image }}.oci.sha256" | |
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} | |
- name: Get current run image hash code of ${{ matrix.stacks.name }} stack | |
run: | | |
skopeo inspect --format "{{.Digest}}" ${{ matrix.stacks.base_run_container_image }} > hash-code-current-run-image-${{ matrix.stacks.name }} | |
- name: Get current build image hash code of ${{ matrix.stacks.name }} stack | |
if: ${{ matrix.stacks.create_build_image == true }} | |
run: | | |
skopeo inspect --format "{{.Digest}}" ${{ matrix.stacks.base_build_container_image }} > hash-code-current-build-image-${{ matrix.stacks.name }} | |
- name: Upload run image hash code | |
uses: actions/upload-artifact@v4 | |
with: | |
name: hash-code-current-run-image-${{ matrix.stacks.name }} | |
path: hash-code-current-run-image-${{ matrix.stacks.name }} | |
if-no-files-found: error | |
- name: Upload build image hash code | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: hash-code-current-build-image-${{ matrix.stacks.name }} | |
path: hash-code-current-build-image-${{ matrix.stacks.name }} | |
if-no-files-found: error | |
- name: Compare previous and current hash codes | |
id: compare_previous_and_current_sha256_hash_codes | |
run: | | |
if [ "$(cat previous_${{ matrix.stacks.run_image }}.oci.sha256)" != "$(cat hash-code-current-run-image-${{ matrix.stacks.name }})" ]; then | |
echo "images_need_update=true" >> "$GITHUB_OUTPUT" | |
fi | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
if [ "$(cat previous_${{ matrix.stacks.build_image }}.oci.sha256)" != "$(cat hash-code-current-build-image-${{ matrix.stacks.name }})" ]; then | |
echo "images_need_update=true" >> "$GITHUB_OUTPUT" | |
fi | |
fi | |
stack_files_changed: | |
name: Determine If Stack Files Changed | |
runs-on: ubuntu-22.04 | |
needs: [ poll_images, preparation ] | |
if: ${{ ! ( needs.poll_images.outputs.images_need_update == null && github.event_name == 'schedule' ) }} | |
strategy: | |
matrix: | |
stacks: ${{ fromJSON(needs.preparation.outputs.stacks) }} | |
outputs: | |
stack_files_changed: ${{ steps.compare.outputs.stack_files_changed }} | |
steps: | |
- name: Checkout With History | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # gets full history | |
- name: Compare With Previous Release | |
id: compare | |
run: | | |
# shellcheck disable=SC2046 | |
changed="$(git diff --name-only $(git describe --tags --abbrev=0) -- ${{ matrix.stacks.config_dir }})" | |
if [ -n "${changed}" ] | |
then | |
echo "Relevant files of ${{ matrix.stacks.name }}, have changed since previous release." | |
echo "${changed}" | |
echo "stack_files_changed=true" >> "$GITHUB_OUTPUT" | |
fi | |
run_if_stack_files_changed: | |
name: Run If Stack Files Changed | |
runs-on: ubuntu-22.04 | |
needs: [stack_files_changed] | |
if: ${{ needs.stack_files_changed.outputs.stack_files_changed == 'true' }} | |
steps: | |
- name: Run if stack files changed | |
run: | | |
echo "stack files have changed" | |
create_stack: | |
name: Create Stack | |
needs: [ poll_images, preparation ] | |
if: ${{ ! ( needs.poll_images.outputs.images_need_update == null && github.event_name == 'schedule' ) }} | |
runs-on: ubuntu-22.04 | |
strategy: | |
matrix: | |
stacks: ${{ fromJSON(needs.preparation.outputs.stacks) }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Create stack ${{ matrix.stacks.name }} | |
id: create-stack | |
run: | | |
scripts/create.sh --stack-dir ${{ matrix.stacks.config_dir }} \ | |
--build-dir ${{ matrix.stacks.output_dir }} | |
- name: Generate Package Receipts | |
id: receipts | |
run: | | |
scripts/receipts.sh --build-image "${{ matrix.stacks.output_dir }}/build.oci" \ | |
--run-image "${{ matrix.stacks.output_dir }}/run.oci" \ | |
--build-receipt current-build-receipt-${{ matrix.stacks.name }} \ | |
--run-receipt current-run-receipt-${{ matrix.stacks.name }} | |
echo "build_receipt=current-build-receipt-${{ matrix.stacks.name }}" >> "$GITHUB_OUTPUT" | |
echo "run_receipt=current-run-receipt-${{ matrix.stacks.name }}" >> "$GITHUB_OUTPUT" | |
- name: Upload run image | |
uses: actions/upload-artifact@v4 | |
with: | |
name: current-run-image-${{ matrix.stacks.name }} | |
path: "${{ matrix.stacks.output_dir }}/run.oci" | |
if-no-files-found: error | |
- name: Upload build image | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: current-build-image-${{ matrix.stacks.name }} | |
path: "${{ matrix.stacks.output_dir }}/build.oci" | |
if-no-files-found: error | |
- name: Upload Build receipt | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: current-build-receipt-${{ matrix.stacks.name }} | |
path: ${{ steps.receipts.outputs.build_receipt }} | |
if-no-files-found: error | |
- name: Upload Run receipt | |
uses: actions/upload-artifact@v4 | |
with: | |
name: current-run-receipt-${{ matrix.stacks.name }} | |
path: ${{ steps.receipts.outputs.run_receipt }} | |
if-no-files-found: error | |
diff: | |
name: Diff Packages | |
outputs: | |
removed_with_force: ${{ steps.removed_with_force.outputs.packages_removed }} | |
needs: [ create_stack, preparation ] | |
runs-on: ubuntu-22.04 | |
strategy: | |
matrix: | |
stacks: ${{ fromJSON(needs.preparation.outputs.stacks) }} | |
steps: | |
- name: Download Build Receipt | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: current-build-receipt-${{ matrix.stacks.name }} | |
- name: Download Run Receipt | |
uses: actions/download-artifact@v4 | |
with: | |
name: current-run-receipt-${{ matrix.stacks.name }} | |
- name: Find and Download Previous Build Receipt | |
id: download_previous_build_receipt | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: paketo-buildpacks/github-config/actions/release/find-and-download-asset@main | |
with: | |
asset_pattern: "${{ matrix.stacks.build_receipt_filename }}" | |
search_depth: 1 | |
repo: ${{ github.repository }} | |
output_path: "/github/workspace/previous-build-receipt-${{ matrix.stacks.name }}" | |
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} | |
- name: Find and Download Previous Run Receipt | |
id: download_previous_run_receipt | |
uses: paketo-buildpacks/github-config/actions/release/find-and-download-asset@main | |
with: | |
asset_pattern: "${{ matrix.stacks.run_receipt_filename }}" | |
search_depth: 1 | |
repo: ${{ github.repository }} | |
output_path: "/github/workspace/previous-run-receipt-${{ matrix.stacks.name }}" | |
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} | |
- name: Write Empty Previous Run Receipts | |
if: ${{ steps.download_previous_run_receipt.outputs.output_path == '' }} | |
run: | | |
echo '{"components":[]}' > "${{ github.workspace }}/previous-run-receipt-${{ matrix.stacks.name }}" | |
- name: Write Empty Previous Build Receipts | |
if: ${{ matrix.stacks.create_build_image == true && steps.download_previous_build_receipt.outputs.output_path == '' }} | |
run: | | |
echo '{"components":[]}' > "${{ github.workspace }}/previous-build-receipt-${{ matrix.stacks.name }}" | |
- name: Compare Build Packages | |
id: build_diff | |
if: ${{ matrix.stacks.create_build_image == true }} | |
uses: paketo-buildpacks/github-config/actions/stack/diff-package-receipts@main | |
with: | |
previous: "/github/workspace/previous-build-receipt-${{ matrix.stacks.name }}" | |
current: "/github/workspace/current-build-receipt-${{ matrix.stacks.name }}" | |
- name: Compare Run Packages | |
id: run_diff | |
uses: paketo-buildpacks/github-config/actions/stack/diff-package-receipts@main | |
with: | |
previous: "/github/workspace/previous-run-receipt-${{ matrix.stacks.name }}" | |
current: "/github/workspace/current-run-receipt-${{ matrix.stacks.name }}" | |
- name: Fail If Packages Removed | |
id: removed_with_force | |
run: | | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
build=$(jq '. | length' <<< "${BUILD_REMOVED}") | |
echo "Build packages removed: ${build}" | |
fi | |
run=$(jq '. | length' <<< "${RUN_REMOVED}") | |
echo "Run packages removed: ${run}" | |
# only fail if packages are removed AND the release has not been forced | |
if ([ "${build}" -gt 0 ] && [ "${{ matrix.stacks.create_build_image }}" == "true" ]) || [ "${run}" -gt 0 ]; then | |
if [ "${{ github.event.inputs.force }}" != 'true' ]; then | |
echo "Packages removed without authorization. Stack cannot be released." | |
exit 1 | |
else | |
echo "packages_removed=true" >> "$GITHUB_OUTPUT" | |
fi | |
fi | |
env: | |
BUILD_REMOVED: ${{ steps.build_diff.outputs.removed }} | |
RUN_REMOVED: ${{ steps.run_diff.outputs.removed }} | |
- name: Create/Upload variable artifacts | |
id: variable_artifacts | |
run: | | |
mkdir -p diff-${{ matrix.stacks.name }} | |
cd diff-${{ matrix.stacks.name }} | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
echo '${{ steps.build_diff.outputs.added }}' > build_added | |
echo '${{ steps.build_diff.outputs.modified }}' > build_modified | |
echo '${{ steps.build_diff.outputs.removed }}' > build_removed_with_force | |
fi | |
echo '${{ steps.run_diff.outputs.added }}' > run_added | |
echo '${{ steps.run_diff.outputs.modified }}' > run_modified | |
echo '${{ steps.run_diff.outputs.removed }}' > run_removed_with_force | |
- name: Upload diff-${{ matrix.stacks.name }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: diff-${{ matrix.stacks.name }} | |
path: diff-${{ matrix.stacks.name }} | |
run_if_packages_removed_with_force: | |
name: Run If Packages Removed With Force | |
needs: [ diff ] | |
runs-on: ubuntu-22.04 | |
if: ${{ needs.diff.outputs.removed_with_force == 'true' }} | |
steps: | |
- name: Run if packages removed with force | |
run: | | |
echo "packages removed with user-provided force" | |
packages_changed: | |
name: Determine If Packages Changed | |
needs: [ diff, preparation ] | |
runs-on: ubuntu-22.04 | |
strategy: | |
matrix: | |
stacks: ${{ fromJSON(needs.preparation.outputs.stacks) }} | |
outputs: | |
packages_changed: ${{ steps.compare.outputs.packages_changed }} | |
steps: | |
- name: Download diff-${{ matrix.stacks.name }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: diff-${{ matrix.stacks.name }} | |
- name: Create env variables | |
run: | | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
echo "BUILD_ADDED=$(cat build_added)" >> $GITHUB_ENV | |
echo "BUILD_MODIFIED=$(cat build_modified)" >> $GITHUB_ENV | |
fi | |
echo "RUN_ADDED=$(cat run_added)" >> $GITHUB_ENV | |
echo "RUN_MODIFIED=$(cat run_modified)" >> $GITHUB_ENV | |
- name: Compare With Previous Release | |
id: compare | |
run: | | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
# shellcheck disable=SC2153 | |
build_added=$(jq '. | length' <<< "${BUILD_ADDED}") | |
echo "Build packages added: ${build_added}" | |
# shellcheck disable=SC2153 | |
build_modified=$(jq '. | length' <<< "${BUILD_MODIFIED}") | |
echo "Build packages modified: ${build_modified}" | |
fi | |
# shellcheck disable=SC2153 | |
run_added=$(jq '. | length' <<< "${RUN_ADDED}") | |
echo "Run packages added: ${run_added}" | |
# shellcheck disable=SC2153 | |
run_modified=$(jq '. | length' <<< "${RUN_MODIFIED}") | |
echo "Run packages modified: ${run_modified}" | |
if [ "${run_added}" -eq 0 ] && [ "${run_modified}" -eq 0 ]; then | |
echo "No packages changed." | |
# we dont set the "packages_changed" to false, as is already null | |
# and also due to parallelization, it will override any true value | |
else | |
echo "Packages changed." | |
echo "packages_changed=true" >> "$GITHUB_OUTPUT" | |
fi | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
if [ "${build_added}" -eq 0 ] && [ "${build_modified}" -eq 0 ]; then | |
echo "No packages changed." | |
# we dont set the "packages_changed" to false, as is already null | |
# and also due to parallelization, it will override the value | |
else | |
echo "Packages changed." | |
echo "packages_changed=true" >> "$GITHUB_OUTPUT" | |
fi | |
fi | |
run_if_packages_changed: | |
name: Run If Packages Changed | |
runs-on: ubuntu-22.04 | |
needs: [packages_changed] | |
if: ${{ needs.packages_changed.outputs.packages_changed == 'true' }} | |
steps: | |
- name: Run if packages changed | |
run: | | |
echo "packages have changed" | |
test: | |
name: Acceptance Test | |
needs: [ create_stack, preparation ] | |
runs-on: ubuntu-22.04 | |
steps: | |
- name: Setup Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: 'stable' | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: tests ran | |
run: echo "tests ran" | |
- name: Download Build images | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: | | |
current-build-image-* | |
- name: Download Run images | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: | | |
current-run-image-* | |
- name: Create OCI artifacts destination directory | |
run: | | |
echo '${{ needs.preparation.outputs.stacks }}' | jq -c '.[]' | while read -r stack; do | |
name=$(echo "$stack" | jq -r '.name') | |
output_dir=$(echo "$stack" | jq -r '.output_dir') | |
create_build_image=$(echo "$stack" | jq -r '.create_build_image') | |
mkdir $output_dir | |
mv "current-run-image-${name}/run.oci" "${output_dir}/run.oci" | |
if [ $create_build_image == 'true' ]; then | |
mv "current-build-image-${name}/build.oci" "${output_dir}/build.oci" | |
fi | |
done | |
- name: Run Acceptance Tests | |
run: ./scripts/test.sh | |
force_release_creation: | |
name: Force Release Creation | |
runs-on: ubuntu-22.04 | |
if: ${{github.event.inputs.force == 'true'}} | |
steps: | |
- name: Signal force release creation | |
run: | | |
echo "Force release creation input set to true" | |
release: | |
name: Release | |
runs-on: ubuntu-22.04 | |
needs: [create_stack, diff, run_if_stack_files_changed, run_if_packages_changed, run_if_packages_removed_with_force, test, force_release_creation, preparation ] | |
if: ${{ always() && needs.diff.result == 'success' && needs.test.result == 'success' && (needs.run_if_packages_changed.result == 'success' || needs.run_if_stack_files_changed.result == 'success' || needs.force_release_creation.result == 'success' ) }} | |
strategy: | |
matrix: | |
stacks: ${{ fromJSON(needs.preparation.outputs.stacks) }} | |
outputs: | |
tag: ${{ steps.tag.outputs.tag }} | |
steps: | |
- name: Print Release Reasoning | |
run: | | |
printf "Diff Packages: %s\n" "${{ needs.diff.result }}" | |
printf "Acceptance Tests: %s\n" "${{ needs.test.result }}" | |
printf "Run If Packages Changed: %s\n" "${{ needs.run_if_packages_changed.result }}" | |
printf "Run If Packages Removed With Force: %s\n" "${{ needs.run_if_packages_removed_with_force.result }}" | |
printf "Run If Stack Files Changed: %s\n" "${{ needs.run_if_stack_files_changed.result }}" | |
printf "Force Release: %s\n" "${{ github.event.inputs.force }}" | |
- name: Checkout With History | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # gets full history | |
- name: Increment Tag | |
if: github.event.inputs.version == '' | |
id: semver | |
uses: paketo-buildpacks/github-config/actions/tag/increment-tag@main | |
with: | |
allow_head_tagged: true | |
- name: Set Release Tag | |
id: tag | |
run: | | |
tag="${{ github.event.inputs.version }}" | |
if [ -z "${tag}" ]; then | |
tag="${{ steps.semver.outputs.tag }}" | |
fi | |
echo "tag=${tag}" >> "$GITHUB_OUTPUT" | |
- name: Get Repository Name | |
id: repo_name | |
run: | | |
full=${{ github.repository }} | |
# Strip off the org and slash from repo name | |
# paketo-buildpacks/jammy-base-stack --> jammy-base-stack | |
repo=$(echo "${full}" | sed 's/^.*\///') | |
echo "github_repo_name=${repo}" >> "$GITHUB_OUTPUT" | |
# Strip off 'stack' suffix from repo name | |
# paketo-buildpacks/jammy-base-stack --> jammy-base | |
registry_repo="${repo//-stack/}" | |
echo "registry_repo_name=${registry_repo}" >> "$GITHUB_OUTPUT" | |
- name: Download diff-${{ matrix.stacks.name }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: diff-${{ matrix.stacks.name }} | |
- name: Release notes preparation | |
id: release_notes_preparation | |
run: | | |
if [ "${{ matrix.stacks.create_build_image }}" == "true" ]; then | |
echo "build_image=${{ needs.preparation.outputs.repo_owner }}/${{ matrix.stacks.build_image }}-${{ needs.preparation.outputs.registry_repo_name }}:${{ steps.tag.outputs.tag }}" >> "$GITHUB_OUTPUT" | |
echo "build_added=$(jq -c <<< "$(cat build_added)" )" >> "$GITHUB_OUTPUT" | |
echo "build_modified=$(jq -c <<< "$(cat build_modified)" )" >> "$GITHUB_OUTPUT" | |
echo "build_removed_with_force=$(jq -c <<< "$(cat build_removed_with_force)" )" >> "$GITHUB_OUTPUT" | |
else | |
echo "build_image=" >> "$GITHUB_OUTPUT" | |
echo "build_added=" >> "$GITHUB_OUTPUT" | |
echo "build_modified=" >> "$GITHUB_OUTPUT" | |
echo "build_removed_with_force=" >> "$GITHUB_OUTPUT" | |
fi | |
echo "run_image=${{ needs.preparation.outputs.repo_owner }}/${{ matrix.stacks.run_image }}-${{ needs.preparation.outputs.registry_repo_name }}:${{ steps.tag.outputs.tag }}" >> "$GITHUB_OUTPUT" | |
echo "run_added=$(jq -c <<< "$(cat run_added)" )" >> "$GITHUB_OUTPUT" | |
echo "run_modified=$(jq -c <<< "$(cat run_modified)" )" >> "$GITHUB_OUTPUT" | |
echo "run_removed_with_force=$(jq -c <<< "$(cat run_removed_with_force)" )" >> "$GITHUB_OUTPUT" | |
- name: Fetch Receipts show limit | |
id: fetch_receipts_show_limit | |
run: | | |
if [[ -f ${{ env.STACKS_FILENAME }} ]]; then | |
echo "receipts_show_limit=$( jq -r '.receipts_show_limit // ""' ${{ env.STACKS_FILENAME }} )" >> "$GITHUB_OUTPUT" | |
fi | |
- name: Create Release Notes | |
id: notes | |
uses: paketo-buildpacks/github-config/actions/stack/release-notes@main | |
with: | |
build_image: ${{ steps.release_notes_preparation.outputs.build_image }} | |
run_image: ${{ steps.release_notes_preparation.outputs.run_image }} | |
build_packages_added: ${{ steps.release_notes_preparation.outputs.build_added }} | |
build_packages_modified: ${{ steps.release_notes_preparation.outputs.build_modified }} | |
build_packages_removed_with_force: ${{ steps.release_notes_preparation.outputs.build_removed_with_force }} | |
run_packages_added: ${{ steps.release_notes_preparation.outputs.run_added }} | |
run_packages_modified: ${{ steps.release_notes_preparation.outputs.run_modified }} | |
run_packages_removed_with_force: ${{ steps.release_notes_preparation.outputs.run_removed_with_force }} | |
receipts_show_limit: ${{ steps.fetch_receipts_show_limit.outputs.receipts_show_limit }} | |
supports_usns: ${{ needs.preparation.outputs.support_usns }} | |
- name: Setup Release Assets | |
id: assets | |
run: | | |
assets="$(jq --null-input --compact-output \ | |
--arg tag "${{ steps.tag.outputs.tag }}" \ | |
--arg repo "${{ steps.repo_name.outputs.github_repo_name }}" \ | |
--arg build_receipt "${{ matrix.stacks.build_receipt_filename }}" \ | |
--arg run_receipt "${{ matrix.stacks.run_receipt_filename }}" \ | |
'[ | |
{ | |
"path": ("current-build-image-${{ matrix.stacks.name }}/build" + ".oci"), | |
"name": ($repo + "-" + $tag + "-" + "${{ matrix.stacks.build_image }}.oci"), | |
"content_type": "application/gzip" | |
}, | |
{ | |
"path": ("current-run-image-${{ matrix.stacks.name }}/run" + ".oci"), | |
"name": ($repo + "-" + $tag + "-" + "${{ matrix.stacks.run_image }}.oci"), | |
"content_type": "application/gzip" | |
}, | |
{ | |
"path": ("current-build-receipt-${{ matrix.stacks.name }}"), | |
"name": ($repo + "-" + $tag + "-" + $build_receipt), | |
"content_type": "text/plain" | |
}, | |
{ | |
"path": ("current-run-receipt-${{ matrix.stacks.name }}"), | |
"name": ($repo + "-" + $tag + "-" + $run_receipt), | |
"content_type": "text/plain" | |
}, | |
{ | |
"path": ("hash-code-current-build-image-${{ matrix.stacks.name }}"), | |
"name": ($repo + "-" + $tag + "-" + "${{ matrix.stacks.build_image }}.oci.sha256"), | |
"content_type": "application/gzip" | |
}, | |
{ | |
"path": ("hash-code-current-run-image-${{ matrix.stacks.name }}"), | |
"name": ($repo + "-" + $tag + "-" + "${{ matrix.stacks.run_image }}.oci.sha256"), | |
"content_type": "application/gzip" | |
}]')" | |
# Exclude/filter the assets that are not required for the release. | |
if [ "${{ matrix.stacks.create_build_image }}" == "false" ]; then | |
assets=$(jq -c --arg stack_name "${{ matrix.stacks.name }}" '[ | |
.[] | |
| select( | |
.path | |
| (contains("current-build-image-" + $stack_name + "/build.oci") | |
or contains("hash-code-current-build-image-" + $stack_name) | |
or contains("current-build-receipt-" + $stack_name)) | |
| not | |
) | |
]' <<< "$assets") | |
fi | |
echo "${assets}" > release-assets-${{ matrix.stacks.name }} | |
- name: Save release notes | |
id: save_notes | |
run: | | |
echo '${{ steps.notes.outputs.release_body }}' > release-body-${{ matrix.stacks.name }} | |
- name: Upload release notes of ${{ matrix.stacks.name }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: release-body-${{ matrix.stacks.name }} | |
path: release-body-${{ matrix.stacks.name }} | |
- name: Upload release assets of ${{ matrix.stacks.name }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: release-assets-${{ matrix.stacks.name }} | |
path: release-assets-${{ matrix.stacks.name }} | |
create_release: | |
name: Create Release | |
runs-on: ubuntu-22.04 | |
needs: release | |
if: ${{ always() && needs.release.result == 'success' }} | |
steps: | |
- name: download release assets | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: release-assets-* | |
merge-multiple: true | |
- name: Merge release assets | |
id: merge_release_assets | |
run: | | |
merged_release_assets='[]' | |
for file in release-assets-*; do | |
merged_release_assets=$(jq -s add "$file" <(echo "$merged_release_assets") | jq -c) | |
done | |
printf "assets=%s\n" "${merged_release_assets}" >> "$GITHUB_OUTPUT" | |
- name: Download release bodies | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: release-body-* | |
merge-multiple: true | |
- name: Merge release bodies | |
id: merge_release_bodies | |
run: | | |
touch release_notes | |
for filename in release-body-*; do | |
cat "$filename" >> release_notes | |
echo >> release_notes | |
done | |
- name: Download current build images | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: current-build-image-* | |
- name: Download current run images | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: current-run-image-* | |
- name: Download current hash codes | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: hash-code-* | |
merge-multiple: true | |
- name: Download Build Receipts | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: current-build-receipt-* | |
merge-multiple: true | |
- name: Download Run Receipts | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: current-run-receipt-* | |
merge-multiple: true | |
- name: Create Release | |
uses: paketo-buildpacks/github-config/actions/release/create@main | |
with: | |
repo: ${{ github.repository }} | |
token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} | |
tag_name: v${{ needs.release.outputs.tag }} | |
target_commitish: ${{ github.sha }} | |
name: v${{ needs.release.outputs.tag }} | |
body_filepath: release_notes | |
draft: false | |
assets: ${{ steps.merge_release_assets.outputs.assets }} | |
failure: | |
name: Alert on Failure | |
runs-on: ubuntu-22.04 | |
needs: [preparation, poll_images, create_stack, diff, test, release, create_release, packages_changed, stack_files_changed] | |
if: ${{ always() && needs.preparation.result == 'failure' || needs.poll_images.result == 'failure' || needs.create_stack.result == 'failure' || needs.diff.result == 'failure' || needs.test.result == 'failure' || needs.release.result == 'failure' || needs.create_release.result == 'failure' || needs.packages_changed.result == 'failure' || needs.stack_files_changed.result == 'failure' }} | |
steps: | |
- name: File Failure Alert Issue | |
uses: paketo-buildpacks/github-config/actions/issue/file@main | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
repo: ${{ github.repository }} | |
label: "failure:release" | |
comment_if_exists: true | |
issue_title: "Failure: Create Release workflow" | |
issue_body: | | |
Create Release workflow [failed](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}). | |
Unable to update images. | |
comment_body: | | |
Another failure occurred: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} |