Skip to content

Commit 9063344

Browse files
authored
Added multi-arch support to build scripts (#6)
* Update README with packaging/publishing instructions and set version to 0.8.18 in buildpack.toml * Add multi-arch support for packaging and publishing
1 parent 0b9a148 commit 9063344

8 files changed

Lines changed: 405 additions & 72 deletions

File tree

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,29 @@
44

55
A Cloud Native Buildpack to install gems from a Gemfile
66

7-
87
This will be providing `gems`.
8+
9+
## Packaging
10+
11+
To package this buildpack for consumption:
12+
13+
```bash
14+
./scripts/package.sh --version 0.8.18
15+
```
16+
17+
This will build the buildpack for all target architectures specified in `buildpack.toml` (amd64 and arm64 by default) and create architecture-specific archives in the `build/` directory.
18+
19+
## Publishing
20+
21+
To publish this buildpack to a registry:
22+
23+
```bash
24+
./scripts/publish.sh \
25+
--image-ref 348674388966.dkr.ecr.us-east-1.amazonaws.com/neeto-deploy/paketo/buildpack/bundle-install:0.8.18
26+
```
27+
28+
The script will automatically:
29+
- Read target architectures from `buildpack.toml`
30+
- Detect architecture-specific buildpack archives
31+
- Publish each architecture separately
32+
- Create and push a multi-arch manifest list

buildpack.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ api = "0.7"
77
keywords = ["ruby", "bundler"]
88
name = "Paketo Buildpack for Bundle Install"
99
sbom-formats = ["application/vnd.cyclonedx+json", "application/spdx+json", "application/vnd.syft+json"]
10+
version = "0.8.18"
1011

1112
[[buildpack.licenses]]
1213
type = "Apache-2.0"
@@ -16,5 +17,13 @@ api = "0.7"
1617
include-files = ["bin/build", "bin/detect", "bin/run", "buildpack.toml"]
1718
pre-package = "./scripts/build.sh"
1819

20+
[[targets]]
21+
os = "linux"
22+
arch = "amd64"
23+
24+
[[targets]]
25+
os = "linux"
26+
arch = "arm64"
27+
1928
[[stacks]]
2029
id = "*"

scripts/.util/builders.sh

100644100755
File mode changed.

scripts/.util/print.sh

100644100755
File mode changed.

scripts/.util/tools.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"createpackage": "v1.70.0",
3-
"jam": "v2.8.0",
4-
"pack": "v0.34.2"
2+
"jam": "v2.15.0",
3+
"pack": "v0.38.2",
4+
"yj": "v5.1.0"
55
}

scripts/.util/tools.sh

100644100755
Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,6 @@ function util::tools::pack::install() {
135135

136136
version="$(jq -r .pack "$(dirname "${BASH_SOURCE[0]}")/tools.json")"
137137

138-
local pack_config_enable_experimental
139-
if [ -f "$(dirname "${BASH_SOURCE[0]}")/../options.json" ]; then
140-
pack_config_enable_experimental="$(jq -r .pack_config_enable_experimental "$(dirname "${BASH_SOURCE[0]}")/../options.json")"
141-
else
142-
pack_config_enable_experimental="false"
143-
fi
144-
145138
tmp_location="/tmp/pack.tgz"
146139
curl_args=(
147140
"--fail"
@@ -165,66 +158,64 @@ function util::tools::pack::install() {
165158
tar xzf "${tmp_location}" -C "${dir}"
166159
chmod +x "${dir}/pack"
167160

168-
if [[ "${pack_config_enable_experimental}" == "true" ]]; then
169-
"${dir}"/pack config experimental true
170-
fi
171-
172161
rm "${tmp_location}"
173162
else
174163
util::print::info "Using pack $("${dir}"/pack version)"
175164
fi
176165
}
177166

178-
function util::tools::packager::install () {
179-
local dir
180-
while [[ "${#}" != 0 ]]; do
181-
case "${1}" in
182-
--directory)
183-
dir="${2}"
184-
shift 2
185-
;;
167+
function util::tools::yj::install() {
168+
local dir token
169+
token=""
186170

187-
*)
188-
util::print::error "unknown argument \"${1}\""
189-
;;
171+
while [[ "${#}" != 0 ]]; do
172+
case "${1}" in
173+
--directory)
174+
dir="${2}"
175+
shift 2
176+
;;
190177

191-
esac
192-
done
178+
--token)
179+
token="${2}"
180+
shift 2
181+
;;
193182

194-
mkdir -p "${dir}"
195-
util::tools::path::export "${dir}"
183+
*)
184+
util::print::error "unknown argument \"${1}\""
185+
esac
186+
done
196187

197-
if [[ ! -f "${dir}/packager" ]]; then
198-
util::print::title "Installing packager"
199-
GOBIN="${dir}" go install github.com/cloudfoundry/libcfbuildpack/packager@latest
200-
fi
201-
}
188+
mkdir -p "${dir}"
189+
util::tools::path::export "${dir}"
190+
191+
if [[ ! -f "${dir}/yj" ]]; then
192+
local version curl_args os arch
202193

203-
function util::tools::create-package::install () {
204-
local dir version
205-
while [[ "${#}" != 0 ]]; do
206-
case "${1}" in
207-
--directory)
208-
dir="${2}"
209-
shift 2
210-
;;
194+
version="$(jq -r .yj "$(dirname "${BASH_SOURCE[0]}")/tools.json")"
195+
196+
curl_args=(
197+
"--fail"
198+
"--silent"
199+
"--location"
200+
"--output" "${dir}/yj"
201+
)
211202

212-
*)
213-
util::print::error "unknown argument \"${1}\""
214-
;;
203+
if [[ "${token}" != "" ]]; then
204+
curl_args+=("--header" "Authorization: Token ${token}")
205+
fi
215206

216-
esac
217-
done
207+
util::print::title "Installing yj ${version}"
218208

219-
version="$(jq -r .createpackage "$(dirname "${BASH_SOURCE[0]}")/tools.json")"
209+
os=$(util::tools::os macos)
210+
arch=$(util::tools::arch)
220211

221-
mkdir -p "${dir}"
222-
util::tools::path::export "${dir}"
212+
curl "https://github.com/sclevine/yj/releases/download/${version}/yj-${os}-${arch}" \
213+
"${curl_args[@]}"
223214

224-
if [[ ! -f "${dir}/create-package" ]]; then
225-
util::print::title "Installing create-package"
226-
GOBIN="${dir}" go install -ldflags="-s -w" "github.com/paketo-buildpacks/libpak/cmd/create-package@${version}"
227-
fi
215+
chmod +x "${dir}/yj"
216+
else
217+
util::print::info "Using yj $("${dir}"/yj -v)"
218+
fi
228219
}
229220

230221
function util::tools::tests::checkfocus() {

scripts/package.sh

Lines changed: 114 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,60 @@ function main {
6969
buildpack_type=extension
7070
fi
7171

72-
buildpack::archive "${version}" "${buildpack_type}"
73-
buildpackage::create "${output}" "${buildpack_type}"
72+
# Read targets from buildpack.toml
73+
local -a targets=()
74+
local buildpack_toml="${ROOT_DIR}/buildpack.toml"
75+
if [[ -f "${buildpack_toml}" ]]; then
76+
util::print::info "Reading targets from ${buildpack_toml}..."
77+
local targets_json
78+
targets_json=$(cat "${buildpack_toml}" | yj -tj | jq -r '.targets[]? | "\(.os)/\(.arch)"' 2>/dev/null || echo "")
79+
80+
if [[ -n "${targets_json}" ]]; then
81+
while IFS= read -r target; do
82+
if [[ -n "${target}" ]]; then
83+
targets+=("${target}")
84+
fi
85+
done <<< "${targets_json}"
86+
util::print::info "Found ${#targets[@]} target(s) in buildpack.toml: ${targets[*]}"
87+
fi
88+
fi
89+
90+
if [[ ${#targets[@]} -gt 0 ]]; then
91+
# Build and package for each target architecture separately
92+
local arch_outputs=()
93+
for target in "${targets[@]}"; do
94+
local arch
95+
arch=$(echo "${target}" | cut -d'/' -f2)
96+
util::print::title "Building binaries for ${target} (arch: ${arch})..."
97+
98+
# Clean bin directory before building for this architecture
99+
rm -rf "${ROOT_DIR}/bin"
100+
mkdir -p "${ROOT_DIR}/bin"
101+
102+
# Build archive for this architecture (GOARCH will be used by jam pack's pre-package script)
103+
export GOARCH="${arch}"
104+
buildpack::archive "${version}" "${buildpack_type}" "${target}"
105+
unset GOARCH
106+
107+
# Package with this target
108+
local arch_output="${output%.cnb}-${arch}.cnb"
109+
arch_outputs+=("${arch_output}")
110+
buildpackage::create "${arch_output}" "${buildpack_type}" "${target}"
111+
done
112+
113+
# Create a combined output by copying the first one (for compatibility)
114+
if [[ ${#arch_outputs[@]} -gt 0 ]]; then
115+
cp "${arch_outputs[0]}" "${output}"
116+
util::print::title "Created architecture-specific packages:"
117+
for arch_output in "${arch_outputs[@]}"; do
118+
echo " - ${arch_output}"
119+
done
120+
echo " - ${output} (copy of ${arch_outputs[0]})"
121+
fi
122+
else
123+
buildpack::archive "${version}" "${buildpack_type}"
124+
buildpackage::create "${output}" "${buildpack_type}"
125+
fi
74126
}
75127

76128
function usage() {
@@ -79,6 +131,8 @@ package.sh --version <version> [OPTIONS]
79131
80132
Packages a buildpack or an extension into a buildpackage .cnb file.
81133
134+
Targets are automatically read from buildpack.toml [[targets]] sections.
135+
82136
OPTIONS
83137
--help -h prints the command usage
84138
--version <version> -v <version> specifies the version number to use when packaging a buildpack or an extension
@@ -106,6 +160,10 @@ function tools::install() {
106160
--directory "${BIN_DIR}" \
107161
--token "${token}"
108162

163+
util::tools::yj::install \
164+
--directory "${BIN_DIR}" \
165+
--token "${token}"
166+
109167
if [[ -f "${ROOT_DIR}/.libbuildpack" ]]; then
110168
util::tools::packager::install \
111169
--directory "${BIN_DIR}"
@@ -120,8 +178,16 @@ function buildpack::archive() {
120178
local version
121179
version="${1}"
122180
buildpack_type="${2}"
181+
local target="${3:-}"
182+
183+
local archive_name="buildpack.tgz"
184+
if [[ -n "${target}" ]]; then
185+
local arch
186+
arch=$(echo "${target}" | cut -d'/' -f2)
187+
archive_name="buildpack-${arch}.tgz"
188+
fi
123189

124-
util::print::title "Packaging ${buildpack_type} into ${BUILD_DIR}/buildpack.tgz..."
190+
util::print::title "Packaging ${buildpack_type} into ${BUILD_DIR}/${archive_name}..."
125191

126192
if [[ -f "${ROOT_DIR}/.libbuildpack" ]]; then
127193
packager \
@@ -133,36 +199,67 @@ function buildpack::archive() {
133199
jam pack \
134200
"--${buildpack_type}" "${ROOT_DIR}/${buildpack_type}.toml"\
135201
--version "${version}" \
136-
--output "${BUILD_DIR}/buildpack.tgz"
202+
--output "${BUILD_DIR}/${archive_name}"
137203
fi
138204
}
139205

140206
function buildpackage::create() {
141-
local output
207+
local output buildpack_type
142208
output="${1}"
143209
buildpack_type="${2}"
210+
shift 2
211+
local targets=("${@:-}")
144212

145213
util::print::title "Packaging ${buildpack_type}... ${output}"
146214

215+
# Determine archive path based on target
216+
local archive_path="${BUILD_DIR}/buildpack.tgz"
217+
if [[ ${#targets[@]} -eq 1 ]]; then
218+
local arch
219+
arch=$(echo "${targets[0]}" | cut -d'/' -f2)
220+
archive_path="${BUILD_DIR}/buildpack-${arch}.tgz"
221+
if [[ ! -f "${archive_path}" ]]; then
222+
archive_path="${BUILD_DIR}/buildpack.tgz"
223+
fi
224+
fi
225+
147226
if [ "$buildpack_type" == "extension" ]; then
148227
cwd=$(pwd)
149228
cd ${BUILD_DIR}
150-
mkdir cnbdir
229+
mkdir -p cnbdir
151230
cd cnbdir
152-
cp ../buildpack.tgz .
153-
tar -xvf buildpack.tgz
154-
rm buildpack.tgz
155-
156-
pack \
157-
extension package "${output}" \
158-
--format file
231+
cp "${archive_path}" .
232+
tar -xvf buildpack*.tgz
233+
rm buildpack*.tgz
234+
235+
pack_args=(
236+
extension package "${output}"
237+
--format file
238+
)
239+
240+
if [[ ${#targets[@]} -gt 0 ]]; then
241+
for target in "${targets[@]}"; do
242+
pack_args+=(--target "${target}")
243+
done
244+
fi
245+
246+
pack "${pack_args[@]}"
159247

160248
cd $cwd
161249
else
162-
pack \
163-
buildpack package "${output}" \
164-
--path "${BUILD_DIR}/buildpack.tgz" \
165-
--format file
250+
pack_args=(
251+
buildpack package "${output}"
252+
--path "${archive_path}"
253+
--format file
254+
)
255+
256+
if [[ ${#targets[@]} -gt 0 ]]; then
257+
for target in "${targets[@]}"; do
258+
pack_args+=(--target "${target}")
259+
done
260+
fi
261+
262+
pack "${pack_args[@]}"
166263
fi
167264
}
168265

0 commit comments

Comments
 (0)