Skip to content

Commit 850bc82

Browse files
committed
chore: write build_go_matrix.sh and archive.sh
1 parent bc06a6f commit 850bc82

File tree

5 files changed

+306
-10
lines changed

5 files changed

+306
-10
lines changed

scripts/archive.sh

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env bash
2+
3+
# This script creates an archive containing the given binary, as well as the
4+
# README.md and LICENSE files.
5+
#
6+
# Usage: ./archive.sh --format tar.gz [--output path/to/output.tar.gz] [--sign-darwin] path/to/binary
7+
#
8+
# The --format parameter must be set, and must either be "zip" or "tar.gz".
9+
#
10+
# If the --output parameter is not set, the default output path is the binary
11+
# path (minus any .exe suffix) plus the format extension ".zip" or ".tar.gz".
12+
#
13+
# If --sign-darwin is specified, the zip file is signed with the `codesign`
14+
# utility and then notarized using the `gon` utility, which may take a while.
15+
# $AC_APPLICATION_IDENTITY must be set and the signing certificate must be
16+
# imported for this to work. Also, the input binary must already be signed with
17+
# the `codesign` tool.
18+
19+
set -euo pipefail
20+
# shellcheck source=lib.sh
21+
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
22+
23+
format=""
24+
output_path=""
25+
sign_darwin=0
26+
27+
args="$(getopt -o "" -l version:,output:,slim,sign-darwin -- "$@")"
28+
eval set -- "$args"
29+
while true; do
30+
case "$1" in
31+
--format)
32+
format="${2#.}"
33+
if [[ "$format" != "zip" ]] && [[ "$format" != "tar.gz" ]]; then
34+
error "Invalid --format parameter '$format', must be 'zip' or 'tar.gz'"
35+
fi
36+
shift 2
37+
;;
38+
--output)
39+
# realpath fails if the dir doesn't exist.
40+
mkdir -p "$(dirname "$2")"
41+
output_path="$(realpath "$2")"
42+
shift 2
43+
;;
44+
--sign-darwin)
45+
if [[ "${AC_APPLICATION_IDENTITY:-}" == "" ]]; then
46+
error "AC_APPLICATION_IDENTITY must be set when --sign-darwin is supplied"
47+
fi
48+
sign_darwin=1
49+
shift
50+
;;
51+
--)
52+
shift
53+
break
54+
;;
55+
*)
56+
error "Unrecognized option: $1"
57+
;;
58+
esac
59+
done
60+
61+
if [[ "$#" != 1 ]]; then
62+
error "Exactly one argument must be provided to this script"
63+
fi
64+
if [[ ! -f "$1" ]]; then
65+
error "File '$1' does not exist or is not a regular file"
66+
fi
67+
input_file="$(realpath "$1")"
68+
69+
# Determine default output path.
70+
if [[ "$output_path" == "" ]]; then
71+
output_path="${input_file%.exe}"
72+
output_path+=".$format"
73+
fi
74+
75+
# Determine the filename of the binary inside the archive.
76+
output_file="coder"
77+
if [[ "$input_file" == *".exe" ]]; then
78+
output_file+=".exe"
79+
fi
80+
81+
# Make temporary dir where all source files intended to be in the archive will
82+
# be symlinked from.
83+
cdroot
84+
temp_dir="$(mktemp -d)"
85+
ln -s "$input_file" "$temp_dir/$output_path"
86+
ln -s README.md "$temp_dir/"
87+
ln -s LICENSE "$temp_dir/"
88+
89+
# Ensure parent output dir.
90+
mkdir -p "$(dirname "$output_path")"
91+
92+
cd "$temp_dir"
93+
if [[ "$format" == "zip" ]]; then
94+
zip "$output_path" ./*
95+
else
96+
tar -czvf "$output_path" ./*
97+
fi
98+
99+
rm -rf "$temp_dir"
100+
101+
if [[ "$sign_darwin" == 1 ]]; then
102+
echo "Notarizing binary..."
103+
execrelative ./sign_darwin.sh "$output_path"
104+
fi

scripts/build_go.sh

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,31 @@
22

33
# This script builds a single Go binary of Coder with the given parameters.
44
#
5-
# Usage: ./build_go.sh [--version v1.2.3+devel.abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim]
5+
# Usage: ./build_go.sh [--version 1.2.3+devel.abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim]
66
#
77
# Defaults to linux:amd64 with slim disabled, but can be controlled with GOOS,
88
# GOARCH and CODER_SLIM_BUILD=1. If no version is specified, defaults to the
99
# version from ./version.sh.
1010
#
1111
# Unless overridden via --output, the built binary will be dropped in
12-
# "$repo_root/dist/coder(-slim)?_$version_$os_$arch" (with a ".exe" suffix for
13-
# windows builds) and the absolute path to the binary will be printed to stdout
14-
# on completion.
12+
# "$repo_root/dist/coder_$version_$os_$arch" (with a ".exe" suffix for windows
13+
# builds) and the absolute path to the binary will be printed to stdout on
14+
# completion.
15+
#
16+
# If the --sign-darwin parameter is specified and the OS is darwin, binaries
17+
# will be signed using the `codesign` utility. $AC_APPLICATION_IDENTITY must be
18+
# set and the signing certificate must be imported for this to work.
1519

1620
set -euo pipefail
1721
# shellcheck source=lib.sh
1822
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
23+
cdroot
1924

2025
version=""
2126
os="${GOOS:-linux}"
2227
arch="${GOARCH:-amd64}"
2328
slim="${CODER_SLIM_BUILD:-0}"
29+
sign_darwin=0
2430
output_path=""
2531

2632
args="$(getopt -o "" -l version:,os:,arch:,output:,slim -- "$@")"
@@ -47,6 +53,13 @@ while true; do
4753
slim=1
4854
shift
4955
;;
56+
--sign-darwin)
57+
if [[ "${AC_APPLICATION_IDENTITY:-}" == "" ]]; then
58+
error "AC_APPLICATION_IDENTITY must be set when --sign-darwin is supplied"
59+
fi
60+
sign_darwin=1
61+
shift
62+
;;
5063
--)
5164
shift
5265
break
@@ -57,9 +70,10 @@ while true; do
5770
esac
5871
done
5972

73+
# Remove the "v" prefix.
74+
version="${version#v}"
6075
if [[ "$version" == "" ]]; then
61-
cdself
62-
version="$(./version.sh)"
76+
version="$(execrelative ./version.sh)"
6377
fi
6478

6579
build_args=(
@@ -69,9 +83,6 @@ if [[ "$slim" == 0 ]]; then
6983
build_args+=(-tags embed)
7084
fi
7185

72-
# cd to the root of the repo.
73-
cdroot
74-
7586
# Compute default output path.
7687
if [[ "$output_path" == "" ]]; then
7788
dist_dir="dist"
@@ -88,4 +99,8 @@ CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" go build \
8899
"${build_args[@]}" \
89100
./cmd/coder 1>&2
90101

102+
if [[ "$GOOS" == "darwin" ]] && [[ "$sign_darwin" == 1 ]]; then
103+
codesign -s "$AC_APPLICATION_IDENTITY" -f -v --timestamp --options runtime "$output_path"
104+
fi
105+
91106
echo -n "$output_path"

scripts/build_go_matrix.sh

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#!/usr/bin/env bash
2+
3+
# This script builds multiple Go binaries for Coder with the given OS and
4+
# architecture combinations.
5+
#
6+
# Usage: ./build_go_matrix.sh [--version 1.2.3+devel.abcdef] [--output dist/] [--slim] [--sign-darwin] os1:arch1,arch2 os2:arch1 os1:arch3
7+
#
8+
# If no OS:arch combinations are provided, nothing will happen and no error will
9+
# be returned. Slim builds are disabled by default. If no version is specified,
10+
# defaults to the version from ./version.sh
11+
#
12+
# The --output parameter must be a directory with a trailing slash where all
13+
# files will be dropped with the default name scheme
14+
# `coder_$version_$os_$arch(.exe)?`, or must contain the `{os}` and `{arch}`
15+
# template variables. You may also use `{version}`. Note that for windows builds
16+
# the `.exe` suffix will be appended automatically.
17+
#
18+
# Unless overridden via --output, the built binary will be dropped in
19+
# "$repo_root/dist/coder_$version_$os_$arch" (with a ".exe" suffix for windows
20+
# builds).
21+
#
22+
# If the --sign-darwin parameter is specified, all darwin binaries will be
23+
# signed using the `codesign` utility. $AC_APPLICATION_IDENTITY must be set and
24+
# the signing certificate must be imported for this to work.
25+
26+
set -euo pipefail
27+
# shellcheck source=lib.sh
28+
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
29+
30+
version=""
31+
output_path=""
32+
slim=0
33+
sign_darwin=0
34+
35+
args="$(getopt -o "" -l version:,output:,slim,sign-darwin -- "$@")"
36+
eval set -- "$args"
37+
while true; do
38+
case "$1" in
39+
--version)
40+
version="$2"
41+
shift 2
42+
;;
43+
--output)
44+
# realpath fails if the dir doesn't exist.
45+
mkdir -p "$(dirname "$2")"
46+
output_path="$(realpath "$2")"
47+
shift 2
48+
;;
49+
--slim)
50+
slim=1
51+
shift
52+
;;
53+
--sign-darwin)
54+
if [[ "${AC_APPLICATION_IDENTITY:-}" == "" ]]; then
55+
error "AC_APPLICATION_IDENTITY must be set when --sign-darwin is supplied"
56+
fi
57+
sign_darwin=1
58+
shift
59+
;;
60+
--)
61+
shift
62+
break
63+
;;
64+
*)
65+
error "Unrecognized option: $1"
66+
;;
67+
esac
68+
done
69+
70+
# Verify the output path template.
71+
if [[ "$output_path" == "" ]]; then
72+
# Input paths are relative, so we don't cdroot at the top, but for this case
73+
# we want it to be relative to the root.
74+
cdroot
75+
output_path="dist/coder_{version}_{os}_{arch}"
76+
elif [[ "$output_path" == */ ]]; then
77+
output_path="${output_path}coder_{version_{os}_{arch}"
78+
else
79+
# Verify that it contains {os} and {arch} at least.
80+
if [[ "$output_path" != *"{os}"* ]] || [[ "$output_path" != *"{arch}"* ]]; then
81+
error "Templated output path '$output_path' must contain {os} and {arch}"
82+
fi
83+
fi
84+
85+
# Remove the "v" prefix.
86+
version="${version#v}"
87+
if [[ "$version" == "" ]]; then
88+
version="$(execrelative ./version.sh)"
89+
fi
90+
91+
# Parse the os:arch specs into an array.
92+
specs=()
93+
for spec in "$@"; do
94+
spec_os="$(echo "$spec" | cut -d ":" -f 1)"
95+
if [[ "$spec_os" == "" ]] || [[ "$spec_os" == *" "* ]]; then
96+
error "Could not parse matrix build spec '$spec': invalid OS '$spec_os'"
97+
fi
98+
99+
# No quoting is important here.
100+
for spec_arch in $(echo "$spec" | cut -d ":" -f 2 | tr "," "\n"); do
101+
if [[ "$spec_arch" == "" ]] || [[ "$spec_os" == *" "* ]]; then
102+
error "Could not parse matrix build spec '$spec': invalid architecture '$spec_arch'"
103+
fi
104+
105+
specs+=("$spec_os $spec_arch")
106+
done
107+
done
108+
109+
build_args=()
110+
if [[ "$slim" == 1 ]]; then
111+
build_args+=(--slim)
112+
fi
113+
if [[ "$sign_darwin" == 1 ]]; then
114+
build_args+=(--sign-darwin)
115+
fi
116+
117+
# Build each spec.
118+
for spec in "${specs[@]}"; do
119+
spec_os="$(echo "$spec" | cut -d " " -f 1)"
120+
spec_arch="$(echo "$spec" | cut -d " " -f 2)"
121+
122+
# Craft output path from the template.
123+
spec_output="$output_path"
124+
spec_output="${spec_output//\{os\}/"$spec_os"}"
125+
spec_output="${spec_output//\{arch\}/"$spec_arch"}"
126+
spec_output="${spec_output//\{version\}/"$version"}"
127+
128+
spec_output_binary="$spec_output"
129+
if [[ "$spec_os" == "windows" ]]; then
130+
spec_output_binary+=".exe"
131+
fi
132+
133+
# Ensure parent dir.
134+
mkdir -p "$(dirname "$spec_output")"
135+
136+
echo "--- Building coder for $spec_os $spec_arch ($spec_output_binary)"
137+
execrelative ./build_go.sh \
138+
--version "$version" \
139+
--os "$spec_os" \
140+
--arch "$spec_arch" \
141+
--output "$spec_output_binary" \
142+
"${build_args[@]}"
143+
echo
144+
echo
145+
done

scripts/lib.sh

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,51 @@ set -euo pipefail
88
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
99
PROJECT_ROOT=$(cd "$SCRIPT_DIR" && git rev-parse --show-toplevel)
1010

11+
# pushd is a silent alternative to the real pushd shell command.
12+
pushd() {
13+
command pushd "$@" >/dev/null
14+
}
15+
16+
# popd is a silent alternative to the real popd shell command.
17+
# shellcheck disable=SC2120
18+
popd() {
19+
command popd "$@" >/dev/null
20+
}
21+
22+
# cdself changes directory to the directory of the current script. This should
23+
# not be used in scripts that may be sourced by other scripts.
1124
cdself() {
1225
cd "$SCRIPT_DIR" || error "Could not change directory to '$SCRIPT_DIR'"
1326
}
1427

28+
# cdroot changes directory to the root of the repository.
1529
cdroot() {
1630
cd "$PROJECT_ROOT" || error "Could not change directory to '$PROJECT_ROOT'"
1731
}
1832

33+
# execrelative can be used to execute scripts as if you were in the parent
34+
# directory of the current script. This should not be used in scripts that may
35+
# be sourced by other scripts.
36+
execrelative() {
37+
pushd "$SCRIPT_DIR" || error "Could not change directory to '$SCRIPT_DIR'"
38+
"$@"
39+
popd
40+
}
41+
42+
# realpath returns an absolute path to the given relative path. It will fail if
43+
# the parent directory of the path does not exist. Make sure you are in the
44+
# expected directory before running this to avoid errors.
45+
#
46+
# GNU realpath relies on coreutils, which are not installed or the default on
47+
# Macs out of the box, so we have this mostly working bash alternative instead.
48+
#
1949
# Taken from https://stackoverflow.com/a/3915420 (CC-BY-SA 4.0)
20-
# Fails if the directory doesn't exist.
2150
realpath() {
2251
dir="$(dirname "$1")"
2352
base="$(basename "$1")"
53+
if [[ ! -d "$dir" ]]; then
54+
error "Could not change directory to '$dir': directory does not exist"
55+
fi
2456
echo "$(
2557
cd "$dir" || error "Could not change directory to '$dir'"
2658
pwd -P
File renamed without changes.

0 commit comments

Comments
 (0)