From c7e2a9d93cc10b9653c468d84116c3f488f57de1 Mon Sep 17 00:00:00 2001 From: lispking Date: Sun, 28 Jan 2024 13:53:12 +0800 Subject: [PATCH] issue(#1): Create builder for Move --- .github/workflows/push-image.yml | 67 ++++++++++++ .gitignore | 18 ++++ README.md | 53 +++++++++- builder.toml | 30 ++++++ scripts/.util/print.sh | 51 +++++++++ scripts/.util/tools.json | 3 + scripts/.util/tools.sh | 175 +++++++++++++++++++++++++++++++ scripts/smoke.sh | 123 ++++++++++++++++++++++ 8 files changed, 518 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/push-image.yml create mode 100644 .gitignore create mode 100644 builder.toml create mode 100644 scripts/.util/print.sh create mode 100644 scripts/.util/tools.json create mode 100644 scripts/.util/tools.sh create mode 100644 scripts/smoke.sh diff --git a/.github/workflows/push-image.yml b/.github/workflows/push-image.yml new file mode 100644 index 0000000..7060bec --- /dev/null +++ b/.github/workflows/push-image.yml @@ -0,0 +1,67 @@ +name: Push Builder Image + +# on: +# release: +# types: +# - published + +on: + push: + tags: + - v[0-9]+.* + +permissions: + contents: read + packages: write + +jobs: + push: + name: Push + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Get pack version + id: pack-version + run: | + version=$(jq -r .pack "scripts/.util/tools.json") + echo "version=${version#v}" >> "$GITHUB_OUTPUT" + + - name: Install Global Pack + uses: buildpacks/github-actions/setup-pack@main + with: + pack-version: ${{ steps.pack-version.outputs.version }} + + - name: Create Builder Image + run: | + pack builder create builder --config builder.toml + + - name: Set environment variable + run: echo "IMAGE_NAME=ghcr.io/${{ github.repository }}" >> $GITHUB_ENV + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + + - name: Push To ghcr.io + run: | + registry_uri="ghcr.io" + registry_repo="${{ github.repository }}" + version="${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" + version=${version#v} + + docker tag builder "${registry_uri}/${registry_repo}:latest" + docker tag builder "${registry_uri}/${registry_repo}:${version}" + + docker push "${registry_uri}/${registry_repo}:latest" + docker push "${registry_uri}/${registry_repo}:${version}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88bbcad --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Copyright (c) The Amphitheatre Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +bin/ +dependencies/ +package/ +scratch/ diff --git a/README.md b/README.md index d1a90a2..2482367 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,51 @@ -# move-builder -A Cloud Native Buildpacks (CNB) builder with Paketo stacks (Jammy Jellyfish) and Move buildpacks +# `ghcr.io/amp-buildpacks/move-builder` + +A Cloud Native Buildpacks (CNB) builder with Paketo stacks (Jammy Jellyfish) and move-builder + +## Usage + +To create the builder, just run + +```shell +pack builder create /move-builder --config builder.toml +``` + +For example + +```shell +pack builder create amp-buildpacks/move-builder --config builder.toml +``` + +You can then build an app with it using + +```shell +pack build --builder /move-builder +``` + +## Contributing + +If anything feels off, or if you feel that some functionality is missing, please +check out the [contributing +page](https://docs.amphitheatre.app/contributing/). There you will find +instructions for sharing your feedback, building the tool locally, and +submitting pull requests to the project. + +## License + +Copyright (c) The Amphitheatre Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +## Credits + +Heavily inspired by https://github.com/paketo-buildpacks/builder-jammy-tiny diff --git a/builder.toml b/builder.toml new file mode 100644 index 0000000..627dcc9 --- /dev/null +++ b/builder.toml @@ -0,0 +1,30 @@ +# Copyright (c) The Amphitheatre Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +description = "A Cloud Native Buildpacks (CNB) builder with Paketo stacks (Jammy Jellyfish) and move-builder" + +[[buildpacks]] + id = "amp-buildpacks/move" + uri = "docker://ghcr.io/amp-buildpacks/move:0.1.0" + +[[order]] + + [[order.group]] + id = "amp-buildpacks/move" + version = "0.1.0" + +[stack] + id = "io.buildpacks.stacks.jammy.tiny" + build-image = "docker.io/paketobuildpacks/build-jammy-tiny" + run-image = "docker.io/paketobuildpacks/run-jammy-tiny" diff --git a/scripts/.util/print.sh b/scripts/.util/print.sh new file mode 100644 index 0000000..0c5a49e --- /dev/null +++ b/scripts/.util/print.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +function util::print::title() { + local blue reset message + blue="\033[0;34m" + reset="\033[0;39m" + message="${1}" + + echo -e "\n${blue}${message}${reset}" >&2 +} + +function util::print::info() { + local message + message="${1}" + + echo -e "${message}" >&2 +} + +function util::print::error() { + local message red reset + message="${1}" + red="\033[0;31m" + reset="\033[0;39m" + + echo -e "${red}${message}${reset}" >&2 + exit 1 +} + +function util::print::success() { + local message green reset + message="${1}" + green="\033[0;32m" + reset="\033[0;39m" + + echo -e "${green}${message}${reset}" >&2 + exitcode="${2:-0}" + exit "${exitcode}" +} + +function util::print::warn() { + local message yellow reset + message="${1}" + yellow="\033[0;33m" + reset="\033[0;39m" + + echo -e "${yellow}${message}${reset}" >&2 + exit 0 +} diff --git a/scripts/.util/tools.json b/scripts/.util/tools.json new file mode 100644 index 0000000..393cbc7 --- /dev/null +++ b/scripts/.util/tools.json @@ -0,0 +1,3 @@ +{ + "pack": "v0.32.1" +} diff --git a/scripts/.util/tools.sh b/scripts/.util/tools.sh new file mode 100644 index 0000000..8811e5b --- /dev/null +++ b/scripts/.util/tools.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +# shellcheck source=SCRIPTDIR/print.sh +source "$(dirname "${BASH_SOURCE[0]}")/print.sh" + +function util::tools::os() { + case "$(uname)" in + "Darwin") + echo "${1:-darwin}" + ;; + + "Linux") + echo "linux" + ;; + + *) + util::print::error "Unknown OS \"$(uname)\"" + exit 1 + esac +} + +function util::tools::arch() { + case "$(uname -m)" in + arm64|aarch64) + echo "arm64" + ;; + + amd64|x86_64) + if [[ "${1:-}" == "--blank-amd64" ]]; then + echo "" + else + echo "amd64" + fi + ;; + + *) + util::print::error "Unknown Architecture \"$(uname -m)\"" + exit 1 + esac +} + +function util::tools::path::export() { + local dir + dir="${1}" + + if ! echo "${PATH}" | grep -q "${dir}"; then + PATH="${dir}:$PATH" + export PATH + fi +} + +function util::tools::jam::install() { + local dir token + token="" + + while [[ "${#}" != 0 ]]; do + case "${1}" in + --directory) + dir="${2}" + shift 2 + ;; + + --token) + token="${2}" + shift 2 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + mkdir -p "${dir}" + util::tools::path::export "${dir}" + + if [[ ! -f "${dir}/jam" ]]; then + local version curl_args os arch + + version="$(jq -r .jam "$(dirname "${BASH_SOURCE[0]}")/tools.json")" + + curl_args=( + "--fail" + "--silent" + "--location" + "--output" "${dir}/jam" + ) + + if [[ "${token}" != "" ]]; then + curl_args+=("--header" "Authorization: Token ${token}") + fi + + util::print::title "Installing jam ${version}" + + os=$(util::tools::os) + arch=$(util::tools::arch) + + curl "https://github.com/paketo-buildpacks/jam/releases/download/${version}/jam-${os}-${arch}" \ + "${curl_args[@]}" + + chmod +x "${dir}/jam" + else + util::print::title "Using $("${dir}"/jam version)" + fi +} + +function util::tools::pack::install() { + local dir token + token="" + + while [[ "${#}" != 0 ]]; do + case "${1}" in + --directory) + dir="${2}" + shift 2 + ;; + + --token) + token="${2}" + shift 2 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + mkdir -p "${dir}" + util::tools::path::export "${dir}" + + if [[ ! -f "${dir}/pack" ]]; then + local version curl_args os arch + + version="$(jq -r .pack "$(dirname "${BASH_SOURCE[0]}")/tools.json")" + + tmp_location="/tmp/pack.tgz" + curl_args=( + "--fail" + "--silent" + "--location" + "--output" "${tmp_location}" + ) + + if [[ "${token}" != "" ]]; then + curl_args+=("--header" "Authorization: Token ${token}") + fi + + util::print::title "Installing pack ${version}" + + os=$(util::tools::os macos) + arch=$(util::tools::arch --blank-amd64) + + curl "https://github.com/buildpacks/pack/releases/download/${version}/pack-${version}-${os}${arch:+-$arch}.tgz" \ + "${curl_args[@]}" + + tar xzf "${tmp_location}" -C "${dir}" + chmod +x "${dir}/pack" + + rm "${tmp_location}" + else + util::print::info "Using pack $("${dir}"/pack version)" + fi +} + +function util::tools::tests::checkfocus() { + testout="${1}" + if grep -q 'Focused: [1-9]' "${testout}"; then + echo "Detected Focused Test(s) - setting exit code to 197" + rm "${testout}" + util::print::success "** GO Test Succeeded **" 197 + fi + rm "${testout}" +} diff --git a/scripts/smoke.sh b/scripts/smoke.sh new file mode 100644 index 0000000..225f5c7 --- /dev/null +++ b/scripts/smoke.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +readonly PROGDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly BUILDERDIR="$(cd "${PROGDIR}/.." && pwd)" + +# shellcheck source=SCRIPTDIR/.util/tools.sh +source "${PROGDIR}/.util/tools.sh" + +# shellcheck source=SCRIPTDIR/.util/print.sh +source "${PROGDIR}/.util/print.sh" + +function main() { + local name token + token="" + + while [[ "${#}" != 0 ]]; do + case "${1}" in + --help|-h) + shift 1 + usage + exit 0 + ;; + + --name|-n) + name="${2}" + shift 2 + ;; + + --token|-t) + token="${2}" + shift 2 + ;; + + "") + # skip if the argument is empty + shift 1 + ;; + + *) + util::print::error "unknown argument \"${1}\"" + esac + done + + if [[ ! -d "${BUILDERDIR}/smoke" ]]; then + util::print::warn "** WARNING No Smoke tests **" + fi + + if [[ -z "${name:-}" ]]; then + name="testbuilder" + fi + + tools::install "${token}" + + builder::create "${name}" + image::pull::lifecycle "${name}" + tests::run "${name}" +} + +function usage() { + cat <<-USAGE +smoke.sh [OPTIONS] + +Runs the smoke test suite. + +OPTIONS + --help -h prints the command usage + --name -n sets the name of the builder that is built for testing + --token Token used to download assets from GitHub (e.g. jam, pack, etc) (optional) +USAGE +} + +function tools::install() { + local token + token="${1}" + + util::tools::pack::install \ + --directory "${BUILDERDIR}/.bin" \ + --token "${token}" +} + +function builder::create() { + local name + name="${1}" + + util::print::title "Creating builder..." + pack builder create "${name}" --config "${BUILDERDIR}/builder.toml" +} + +function image::pull::lifecycle() { + local name lifecycle_image + name="${1}" + + lifecycle_image="index.docker.io/buildpacksio/lifecycle:$( + pack builder inspect "${name}" --output json \ + | jq -r '.local_info.lifecycle.version' + )" + + util::print::title "Pulling lifecycle image..." + docker pull "${lifecycle_image}" +} + +function tests::run() { + local name + name="${1}" + + util::print::title "Run Builder Smoke Tests" + + export CGO_ENABLED=0 + testout=$(mktemp) + pushd "${BUILDERDIR}" > /dev/null + if GOMAXPROCS="${GOMAXPROCS:-4}" go test -count=1 -timeout 0 ./smoke/... -v -run Smoke --name "${name}" | tee "${testout}"; then + util::tools::tests::checkfocus "${testout}" + util::print::success "** GO Test Succeeded **" + else + util::print::error "** GO Test Failed **" + fi + popd > /dev/null +} + +main "${@:-}"