Skip to content

Commit 9e8cde5

Browse files
committed
release.sh: make reproducible .zip and .tar.gz
Took the code for reproducible packing from LND.
1 parent 0e30dc9 commit 9e8cde5

File tree

1 file changed

+113
-21
lines changed

1 file changed

+113
-21
lines changed

release.sh

Lines changed: 113 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,24 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
1616
# Checkout the repo to a subdir to clean from clean from unstaged files and
1717
# build exactly what is committed.
1818
BUILD_DIR="${SCRIPT_DIR}/tmp-build-$(date +%Y%m%d-%H%M%S)"
19-
mkdir -p $BUILD_DIR
20-
cd $BUILD_DIR
21-
git clone --tags "$SCRIPT_DIR" .
19+
20+
# green prints one line of green text (if the terminal supports it).
21+
function green() {
22+
echo -e "\e[0;32m${1}\e[0m"
23+
}
24+
25+
# red prints one line of red text (if the terminal supports it).
26+
function red() {
27+
echo -e "\e[0;31m${1}\e[0m"
28+
}
2229

2330
TAG=''
2431

2532
check_tag() {
2633
# If no tag specified, use date + version otherwise use tag.
2734
if [[ $1x = x ]]; then
2835
TAG=`date +%Y%m%d-%H%M%S`
36+
green "No tag specified, using ${TAG} as tag"
2937

3038
return
3139
fi
@@ -34,7 +42,7 @@ check_tag() {
3442

3543
# If a tag is specified, ensure that tag is present and checked out.
3644
if [[ $TAG != $(git describe) ]]; then
37-
echo "tag $TAG not checked out"
45+
red "tag $TAG not checked out"
3846
exit 1
3947
fi
4048

@@ -48,15 +56,15 @@ check_tag() {
4856
DESCRIBED_HASH=${BASH_REMATCH[1]}
4957
CURRENT_HASH=$(git rev-parse HEAD)
5058
if [[ $CURRENT_HASH != $DESCRIBED_HASH* ]]; then
51-
echo "Described hash $DESCRIBED_HASH is not a prefix of current commit $CURRENT_HASH"
59+
red "Described hash $DESCRIBED_HASH is not a prefix of current commit $CURRENT_HASH"
5260
exit 1
5361
fi
5462

5563
return
5664
fi
5765

5866
if ! git verify-tag $TAG; then
59-
echo "tag $TAG not signed"
67+
red "tag $TAG not signed"
6068
exit 1
6169
fi
6270

@@ -75,31 +83,111 @@ check_tag() {
7583

7684
# Match git tag with loop version.
7785
if [[ $TAG != $LOOP_VERSION ]]; then
78-
echo "loop version $LOOP_VERSION does not match tag $TAG"
86+
red "loop version $LOOP_VERSION does not match tag $TAG"
7987
exit 1
8088
fi
8189
else
82-
echo "malformed loop version output"
90+
red "malformed loop version output"
8391
exit 1
8492
fi
8593
}
8694

87-
check_tag $1
95+
# Needed for setting file timestamps to get reproducible archives.
96+
BUILD_DATE="2020-01-01 00:00:00"
97+
BUILD_DATE_STAMP="202001010000.00"
98+
99+
# reproducible_tar_gzip creates a reproducible tar.gz file of a directory. This
100+
# includes setting all file timestamps and ownership settings uniformly.
101+
function reproducible_tar_gzip() {
102+
local dir=$1
103+
local dst=$2
104+
local tar_cmd=tar
105+
106+
# MacOS has a version of BSD tar which doesn't support setting the --mtime
107+
# flag. We need gnu-tar, or gtar for short to be installed for this script to
108+
# work properly.
109+
tar_version=$(tar --version)
110+
if [[ ! "$tar_version" =~ "GNU tar" ]]; then
111+
if ! command -v "gtar"; then
112+
red "GNU tar is required but cannot be found!"
113+
red "On MacOS please run 'brew install gnu-tar' to install gtar."
114+
exit 1
115+
fi
88116

89-
go mod vendor
90-
tar -cvzf vendor.tar.gz vendor
117+
# We have gtar installed, use that instead.
118+
tar_cmd=gtar
119+
fi
120+
121+
# Pin down the timestamp time zone.
122+
export TZ=UTC
123+
124+
find "${dir}" -print0 | LC_ALL=C sort -r -z | $tar_cmd \
125+
"--mtime=${BUILD_DATE}" --no-recursion --null --mode=u+rw,go+r-w,a+X \
126+
--owner=0 --group=0 --numeric-owner -c -T - | gzip -9n > "$dst"
127+
}
128+
129+
# reproducible_zip creates a reproducible zip file of a directory. This
130+
# includes setting all file timestamps.
131+
function reproducible_zip() {
132+
local dir=$1
133+
local dst=$2
134+
135+
# Pin down file name encoding and timestamp time zone.
136+
export TZ=UTC
137+
138+
# Set the date of each file in the directory that's about to be packaged to
139+
# the same timestamp and make sure the same permissions are used everywhere.
140+
chmod -R 0755 "${dir}"
141+
touch -t "${BUILD_DATE_STAMP}" "${dir}"
142+
find "${dir}" -print0 | LC_ALL=C sort -r -z | xargs -0r touch \
143+
-t "${BUILD_DATE_STAMP}"
144+
145+
find "${dir}" | LC_ALL=C sort -r | zip -o -X -r -@ "$dst"
146+
}
147+
148+
##################
149+
# Start Building #
150+
##################
151+
152+
if [ -d "$BUILD_DIR" ]; then
153+
red "Build directory ${BUILD_DIR} already exists!"
154+
exit 1
155+
fi
156+
157+
green " - Cloning to subdir ${BUILD_DIR} to get clean Git"
158+
mkdir -p "$BUILD_DIR"
159+
cd "$BUILD_DIR"
160+
git clone --tags "$SCRIPT_DIR" .
161+
162+
green " - Checking tag $1"
163+
check_tag $1
91164

92165
PACKAGE=loop
93166
ARTIFACTS_DIR="${SCRIPT_DIR}/${PACKAGE}-${TAG}"
94-
mkdir -p $ARTIFACTS_DIR
95-
96-
cp vendor.tar.gz $ARTIFACTS_DIR/
97-
rm vendor.tar.gz
167+
if [ -d "$ARTIFACTS_DIR" ]; then
168+
red "artifacts directory ${ARTIFACTS_DIR} already exists!"
169+
exit 1
170+
fi
171+
green " - Creating artifacts directory ${ARTIFACTS_DIR}"
172+
mkdir -p "$ARTIFACTS_DIR"
173+
green " - Packaging vendor to ${ARTIFACTS_DIR}/vendor.tar.gz"
174+
go mod vendor
175+
reproducible_tar_gzip vendor "${ARTIFACTS_DIR}/vendor.tar.gz"
98176
rm -r vendor
99177

100-
PACKAGESRC="${ARTIFACTS_DIR}/${PACKAGE}-source-${TAG}.tar"
101-
git archive -o $PACKAGESRC HEAD
102-
gzip -f $PACKAGESRC > "$PACKAGESRC.gz"
178+
PACKAGESRC="${ARTIFACTS_DIR}/${PACKAGE}-source-${TAG}.tar.gz"
179+
green " - Creating source archive ${PACKAGESRC}"
180+
TMPSOURCETAR="${ARTIFACTS_DIR}/tmp-${PACKAGE}-source-${TAG}.tar"
181+
PKGSRC="${PACKAGE}-source"
182+
git archive -o "$TMPSOURCETAR" HEAD
183+
cd "$ARTIFACTS_DIR"
184+
mkdir "$PKGSRC"
185+
tar -xf "$TMPSOURCETAR" -C "$PKGSRC"
186+
cd "$PKGSRC"
187+
reproducible_tar_gzip . "$PACKAGESRC"
188+
cd ..
189+
rm -r "$PKGSRC"
190+
rm "$TMPSOURCETAR"
103191

104192
# If LOOPBUILDSYS is set the default list is ignored. Useful to release
105193
# for a subset of systems/architectures.
@@ -109,6 +197,7 @@ PKG="github.com/lightninglabs/loop"
109197
COMMIT=$(git describe --abbrev=40 --dirty)
110198
COMMITFLAGS="-X $PKG/build.Commit=$COMMIT"
111199

200+
cd "$BUILD_DIR"
112201
for i in $SYS; do
113202
OS=$(echo $i | cut -f1 -d-)
114203
ARCH=$(echo $i | cut -f2 -d-)
@@ -125,21 +214,24 @@ for i in $SYS; do
125214
mkdir $PACKAGE-$i-$TAG
126215
cd $PACKAGE-$i-$TAG
127216

128-
echo "Building:" $OS $ARCH $ARM
217+
green "- Building: $OS $ARCH $ARM"
129218
for bin in loop loopd; do
130219
env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -ldflags "$COMMITFLAGS" "github.com/lightninglabs/loop/cmd/$bin"
131220
done
132221
cd ..
133222

134223
if [[ $OS = "windows" ]]; then
135-
zip -r "${ARTIFACTS_DIR}/${PACKAGE}-${i}-${TAG}.zip" "${PACKAGE}-${i}-${TAG}"
224+
green "- Producing ZIP file ${ARTIFACTS_DIR}/${PACKAGE}-${i}-${TAG}.zip"
225+
reproducible_zip "${PACKAGE}-${i}-${TAG}" "${ARTIFACTS_DIR}/${PACKAGE}-${i}-${TAG}.zip"
136226
else
137-
tar -cvzf "${ARTIFACTS_DIR}/${PACKAGE}-${i}-${TAG}.tar.gz" "${PACKAGE}-${i}-${TAG}"
227+
green "- Producing TAR.GZ file ${ARTIFACTS_DIR}/${PACKAGE}-${i}-${TAG}.tar.gz"
228+
reproducible_tar_gzip "${PACKAGE}-${i}-${TAG}" "${ARTIFACTS_DIR}/${PACKAGE}-${i}-${TAG}.tar.gz"
138229
fi
139230

140231
rm -r $PACKAGE-$i-$TAG
141232
done
142233

143234
cd "$ARTIFACTS_DIR"
144235

236+
green "- Producing manifest-$TAG.txt"
145237
shasum -a 256 * > manifest-$TAG.txt

0 commit comments

Comments
 (0)