diff --git a/.github/workflows/update-go-mod-version.yml b/.github/workflows/update-go-mod-version.yml new file mode 100644 index 0000000..a4a9781 --- /dev/null +++ b/.github/workflows/update-go-mod-version.yml @@ -0,0 +1,93 @@ +name: Update Go version + +on: + schedule: + - cron: '21 4 * * MON' # every monday at 4:21 UTC + workflow_dispatch: + +concurrency: update-go + +jobs: + update-go: + name: Update go toolchain in go.mod + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Checkout PR Branch + uses: paketo-buildpacks/github-config/actions/pull-request/checkout-branch@main + with: + branch: automation/go-mod-update/update-main + - name: Setup Go + id: setup-go + uses: actions/setup-go@v5 + with: + go-version: 'stable' + - name: Get current go toolchain version + id: current-go-version + uses: paketo-buildpacks/github-config/actions/update-go-mod-version@main + with: + go-version: ${{ steps.setup-go.outputs.go-version }} + - name: Go mod tidy + run: | + #!/usr/bin/env bash + set -euo pipefail + shopt -s inherit_errexit + + echo "Before running go mod tidy" + echo "head -n10 go.mod " + head -n10 go.mod + + echo "git diff" + git diff + + echo "Running go mod tidy" + go mod tidy + + echo "After running go mod tidy" + echo "head -n10 go.mod " + head -n10 go.mod + + echo "git diff" + git diff + - name: Commit + id: commit + uses: paketo-buildpacks/github-config/actions/pull-request/create-commit@main + with: + message: "Updates go mod version to ${{ steps.setup-go.outputs.go-version }}" + pathspec: "." + keyid: ${{ secrets.PAKETO_BOT_GPG_SIGNING_KEY_ID }} + key: ${{ secrets.PAKETO_BOT_GPG_SIGNING_KEY }} + + - name: Push Branch + if: ${{ steps.commit.outputs.commit_sha != '' }} + uses: paketo-buildpacks/github-config/actions/pull-request/push-branch@main + with: + branch: automation/go-mod-update/update-main + + - name: Open Pull Request + if: ${{ steps.commit.outputs.commit_sha != '' }} + uses: paketo-buildpacks/github-config/actions/pull-request/open@main + with: + token: ${{ secrets.PAKETO_BOT_GITHUB_TOKEN }} + title: "Updates go mod version to ${{ steps.setup-go.outputs.go-version }}" + branch: automation/go-mod-update/update-main + + failure: + name: Alert on Failure + runs-on: ubuntu-22.04 + needs: [update-go] + if: ${{ always() && needs.update-go.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:update-go-version" + comment_if_exists: true + issue_title: "Failure: Update Go Mod Version workflow" + issue_body: | + Update Go Mod Version workflow [failed](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}). + comment_body: | + Another failure occurred: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} diff --git a/scripts/create.sh b/scripts/create.sh index 6c9b6cb..050ad3f 100755 --- a/scripts/create.sh +++ b/scripts/create.sh @@ -5,9 +5,8 @@ set -o pipefail readonly PROG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly ROOT_DIR="$(cd "${PROG_DIR}/.." && pwd)" -readonly STACK_DIR="${ROOT_DIR}/stack" readonly BIN_DIR="${ROOT_DIR}/.bin" -readonly BUILD_DIR="${ROOT_DIR}/build" +readonly IMAGES_JSON="${ROOT_DIR}/images.json" # shellcheck source=SCRIPTDIR/.util/tools.sh source "${PROG_DIR}/.util/tools.sh" @@ -21,6 +20,9 @@ fi function main() { local flags + local stack_dir_name build_dir_name + stack_dir_name="" + build_dir_name="" while [[ "${#}" != 0 ]]; do case "${1}" in @@ -40,6 +42,16 @@ function main() { shift 2 ;; + --stack-dir) + stack_dir_name="${2}" + shift 2 + ;; + + --build-dir) + build_dir_name="${2}" + shift 2 + ;; + "") # skip if the argument is empty shift 1 @@ -50,10 +62,27 @@ function main() { esac done - mkdir -p "${BUILD_DIR}" - tools::install - stack::create "${flags[@]}" + + if [ -f "${IMAGES_JSON}" ]; then + # we need to copy images.json for inclusion in the build image + cp $IMAGES_JSON "${ROOT_DIR}/stack" + fi + + # if stack or build argument is provided but not both, then throw an error + if [[ -n "${stack_dir_name}" && ! -n "${build_dir_name}" ]] || [[ ! -n "${stack_dir_name}" && -n "${build_dir_name}" ]]; then + util::print::error "Both stack-dir and build-dir must be provided" + elif [[ -n "${stack_dir_name}" && -n "${build_dir_name}" ]]; then + stack::create "${ROOT_DIR}/${stack_dir_name}" "${ROOT_DIR}/${build_dir_name}" "${flags[@]}" + elif [ -f "${IMAGES_JSON}" ]; then + jq -c '.images[]' "${IMAGES_JSON}" | while read -r image; do + config_dir=$(echo "${image}" | jq -r '.config_dir') + output_dir=$(echo "${image}" | jq -r '.output_dir') + stack::create "${ROOT_DIR}/${config_dir}" "${ROOT_DIR}/${output_dir}" "${flags[@]}" + done + else + stack::create "${ROOT_DIR}/stack" "${ROOT_DIR}/build" "${flags[@]}" + fi } function usage() { @@ -66,10 +95,11 @@ the repository. OPTIONS --help -h prints the command usage --secret provide a secret in the form key=value. Use flag multiple times to provide multiple secrets + --stack-dir Provide the stack directory relative to the root directory. The default value is 'stack'. + --build-dir Provide the build directory relative to the root directory. The default value is 'build'. USAGE } - function tools::install() { util::tools::jam::install \ --directory "${BIN_DIR}" @@ -77,13 +107,21 @@ function tools::install() { function stack::create() { local flags + local stack_dirpath build_dirpath + + stack_dirpath="${1}" + shift + build_dirpath="${1}" + shift + + mkdir -p "${build_dirpath}" flags=("${@}") args=( - --config "${STACK_DIR}/stack.toml" - --build-output "${BUILD_DIR}/build.oci" - --run-output "${BUILD_DIR}/run.oci" + --config "${stack_dirpath}/stack.toml" + --build-output "${build_dirpath}/build.oci" + --run-output "${build_dirpath}/run.oci" ) args+=("${flags[@]}") diff --git a/scripts/test.sh b/scripts/test.sh index a3e078f..eaa6bd1 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -5,7 +5,8 @@ set -o pipefail readonly PROG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly STACK_DIR="$(cd "${PROG_DIR}/.." && pwd)" -readonly OUTPUT_DIR="${STACK_DIR}/build" +readonly IMAGES_JSON="${STACK_DIR}/images.json" +readonly INTEGRATION_JSON="${STACK_DIR}/integration.json" # shellcheck source=SCRIPTDIR/.util/tools.sh source "${PROG_DIR}/.util/tools.sh" @@ -14,9 +15,11 @@ source "${PROG_DIR}/.util/tools.sh" source "${PROG_DIR}/.util/print.sh" function main() { - local clean token + local clean token registryPort registryPid localRegistry setupLocalRegistry clean="false" token="" + registryPid="" + setupLocalRegistry="" while [[ "${#}" != 0 ]]; do case "${1}" in @@ -50,31 +53,78 @@ function main() { if [[ "${clean}" == "true" ]]; then util::print::title "Cleaning up preexisting stack archives..." - rm -rf "${OUTPUT_DIR}" + clean::stacks fi - if ! [[ -f "${OUTPUT_DIR}/build.oci" ]] || ! [[ -f "${OUTPUT_DIR}/run.oci" ]]; then + stack_output_builds_exist=$(stack_builds_exist) + + if [[ "${stack_output_builds_exist}" == "false" ]]; then util::print::title "Creating stack..." "${STACK_DIR}/scripts/create.sh" fi + if [[ -f $INTEGRATION_JSON ]]; then + setupLocalRegistry=$(jq '.setup_local_registry' $INTEGRATION_JSON) + fi + + if [[ "${setupLocalRegistry}" == "true" ]]; then + registryPort=$(get::random::port) + registryPid=$(local::registry::start $registryPort) + localRegistry="127.0.0.1:$registryPort" + export REGISTRY_URL="${localRegistry}" + fi + tests::run + + if [[ "${setupLocalRegistry}" == "true" ]]; then + kill $registryPid + fi +} + +function join_by { + local d=${1-} f=${2-} + if shift 2; then + printf %s "$f" "${@/#/$d}" + fi } function usage() { + oci_images_arr=() + + if [ -f "${IMAGES_JSON}" ]; then + local images=$(jq -c '.images[]' "${IMAGES_JSON}") + + while read -r image; do + output_dir=$(echo "${image}" | jq -r '.output_dir') + build_image=$(echo "${image}" | jq -r '.build_image') + create_build_image=$(echo "${image}" | jq -r '.create_build_image') + run_image=$(echo "${image}" | jq -r '.run_image') + + if [ $create_build_image == 'true' ]; then + oci_images_arr+=("${STACK_DIR}/${output_dir}/${build_image}.oci") + fi + + oci_images_arr+=("${STACK_DIR}/${output_dir}/${run_image}.oci") + + done <<<"$images" + else + oci_images_arr+=("${STACK_DIR}/build/build.oci") + oci_images_arr+=("${STACK_DIR}/build/run.oci") + fi + + joined_oci_images=$(join_by $'\nand\n' ${oci_images_arr[*]}) + cat <<-USAGE test.sh [OPTIONS] Runs acceptance tests against the stack. Uses the OCI images -${STACK_DIR}/build/build.oci -and -${STACK_DIR}/build/run.oci +${joined_oci_images} if they exist. Otherwise, first runs create.sh to create them. OPTIONS - --clean -c clears contents of stack output directory before running tests - --token Token used to download assets from GitHub (e.g. jam, pack, etc) (optional) - --help -h prints the command usage + --clean -c clears contents of stack output directory before running tests + --token -t Token used to download assets from GitHub (e.g. jam, pack, etc) (optional) + --help -h prints the command usage USAGE } @@ -91,6 +141,10 @@ function tools::install() { --token "${token}" util::tools::skopeo::check + + util::tools::crane::install \ + --directory "${STACK_DIR}/.bin" \ + --token "${token}" } function tests::run() { @@ -108,4 +162,37 @@ function tests::run() { popd > /dev/null } +function stack_builds_exist() { + + local stack_output_builds_exist="true" + if [ -f "${IMAGES_JSON}" ]; then + + local images=$(jq -c '.images[]' "${IMAGES_JSON}") + + while IFS= read -r image; do + stack_output_dir=$(echo "${image}" | jq -r '.output_dir') + if ! [[ -f "${STACK_DIR}/${stack_output_dir}/build.oci" ]] || ! [[ -f "${STACK_DIR}/${stack_output_dir}/run.oci" ]]; then + stack_output_builds_exist="false" + fi + done <<<"$images" + else + if ! [[ -f "${STACK_DIR}/build/build.oci" ]] || ! [[ -f "${STACK_DIR}/build/run.oci" ]]; then + stack_output_builds_exist="false" + fi + fi + + echo "$stack_output_builds_exist" +} + +function clean::stacks(){ + if [ -f "${IMAGES_JSON}" ]; then + jq -c '.images[]' "${IMAGES_JSON}" | while read -r image; do + output_dir=$(echo "${image}" | jq -r '.output_dir') + rm -rf "${STACK_DIR}/${output_dir}" + done + else + rm -rf "${STACK_DIR}/build" + fi +} + main "${@:-}"