-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelease.sh
More file actions
executable file
·326 lines (274 loc) · 11.3 KB
/
Copy pathrelease.sh
File metadata and controls
executable file
·326 lines (274 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#!/usr/bin/env bash
set -euo pipefail
VERSION="${1:?Usage: $0 <version>}"
RELEASE_DIR="release/${VERSION}"
NAME="fastdedup"
DESC="Fast file deduplication using reflinks (btrfs, XFS, ZFS)"
ARCHES=(amd64 arm64 386 arm riscv64 ppc64le s390x mips64le)
MAINTAINER="PHANTOm <phantom@kix.co.il>"
GPG_KEY="B2BE8C2EBFB7AAC6572E933C779CD5498B743A1B"
PPA_SERIES=(jammy noble oracular plucky questing resolute)
PPA_TARGET="phntm-ppa"
# Series that need a bundled Go toolchain (system Go is too old)
BUNDLED_GO_SERIES=(jammy)
BUNDLED_GO_VERSION="1.22.12"
BUNDLED_GO_URL="https://go.dev/dl/go${BUNDLED_GO_VERSION}.linux-amd64.tar.gz"
# Ensure fpm is available
if ! command -v fpm &>/dev/null; then
FPM_PATH="$HOME/.local/share/gem/ruby/$(ruby -e 'puts RUBY_VERSION.sub(/\.\d+$/,".0")')/bin/fpm"
if [[ -x "$FPM_PATH" ]]; then
export PATH="$(dirname "$FPM_PATH"):$PATH"
else
echo "ERROR: fpm not found. Install with: gem install --user-install fpm"
exit 1
fi
fi
mkdir -p "$RELEASE_DIR"
# ── Run tests ──────────────────────────────────────────────────────
echo "==> Running unit tests..."
if ! go test ./...; then
echo "ERROR: unit tests failed — aborting release"
exit 1
fi
echo " tests passed"
# ── Build binaries ──────────────────────────────────────────────────
echo "==> Building binaries for ${#ARCHES[@]} architectures..."
for arch in "${ARCHES[@]}"; do
printf " %-10s" "linux/$arch"
GOOS=linux GOARCH="$arch" go build -ldflags="-s -w -X main.version=${VERSION}" \
-o "${RELEASE_DIR}/${NAME}-linux-${arch}" .
echo "ok"
done
# ── Package with fpm ────────────────────────────────────────────────
echo "==> Creating packages..."
for arch in "${ARCHES[@]}"; do
# Map Go arch → distro arch names
case "$arch" in
amd64) DEB=amd64 RPM=x86_64 APK=x86_64 ;;
arm64) DEB=arm64 RPM=aarch64 APK=aarch64 ;;
386) DEB=i386 RPM=i686 APK=x86 ;;
arm) DEB=armhf RPM=armv7hl APK=armv7 ;;
riscv64) DEB=riscv64 RPM=riscv64 APK=riscv64 ;;
ppc64le) DEB=ppc64el RPM=ppc64le APK=ppc64le ;;
s390x) DEB=s390x RPM=s390x APK=s390x ;;
mips64le) DEB=mips64el RPM=mips64el APK=mips64 ;;
esac
STAGING=$(mktemp -d)
mkdir -p "${STAGING}/usr/bin" "${STAGING}/etc/default" "${STAGING}/etc/logrotate.d"
cp "${RELEASE_DIR}/${NAME}-linux-${arch}" "${STAGING}/usr/bin/${NAME}"
cp debian/fastdedup.default "${STAGING}/etc/default/${NAME}"
cp debian/fastdedup.logrotate "${STAGING}/etc/logrotate.d/${NAME}"
FPM_COMMON=(
-s dir -n "$NAME" -v "$VERSION"
--description "$DESC"
--config-files etc/default/${NAME}
--config-files etc/logrotate.d/${NAME}
-C "$STAGING"
)
FPM_FILES=(usr/bin/${NAME} etc/default/${NAME} etc/logrotate.d/${NAME})
printf " %-10s deb " "linux/$arch"
fpm "${FPM_COMMON[@]}" -t deb -a "$DEB" -p "${RELEASE_DIR}/" "${FPM_FILES[@]}" 2>/dev/null
printf "rpm "
fpm "${FPM_COMMON[@]}" -t rpm -a "$RPM" -p "${RELEASE_DIR}/" "${FPM_FILES[@]}" 2>/dev/null
printf "apk "
fpm "${FPM_COMMON[@]}" -t apk -a "$APK" -p "${RELEASE_DIR}/" "${FPM_FILES[@]}" 2>/dev/null
printf "sh "
fpm "${FPM_COMMON[@]}" -t sh -a "$DEB" -p "${RELEASE_DIR}/${NAME}-${VERSION}-linux-${arch}.sh" "${FPM_FILES[@]}" 2>/dev/null
echo ""
rm -rf "$STAGING"
done
# ── Cron packages (architecture-independent) ─────────────────────────
echo "==> Creating cron packages..."
for variant in daily weekly; do
STAGING=$(mktemp -d)
mkdir -p "${STAGING}/etc/cron.${variant}"
cp debian/fastdedup-cron "${STAGING}/etc/cron.${variant}/${NAME}"
chmod +x "${STAGING}/etc/cron.${variant}/${NAME}"
printf " %-10s deb " "${NAME}-${variant}"
fpm -s dir -n "${NAME}-${variant}" -v "$VERSION" \
--description "$(echo "${variant^}") automatic file deduplication using reflinks" \
--depends "$NAME" \
-a all -C "$STAGING" -t deb -p "${RELEASE_DIR}/" \
etc/cron.${variant}/${NAME} 2>/dev/null
echo "ok"
rm -rf "$STAGING"
done
# ── Ubuntu PPA ──────────────────────────────────────────────────────
echo ""
echo "==> Building Ubuntu PPA source packages..."
# Ensure dput and debuild are available
for cmd in dput debuild; do
if ! command -v "$cmd" &>/dev/null; then
echo "ERROR: $cmd not found. Install with: sudo apt install devscripts dput"
exit 1
fi
done
# Vendor dependencies (needed for offline Launchpad builds)
go mod vendor
# Remove any stale built binary so it doesn't end up in the source tarball
rm -f "${NAME}"
# Save original debian files (will be modified per-series)
# Stored outside debian/ because dh_clean removes .orig files in debian/.
cp debian/control "${RELEASE_DIR}/control.saved"
cp debian/rules "${RELEASE_DIR}/rules.saved"
# Download Go toolchain for bundled-Go series (if any)
needs_bundled=false
for series in "${PPA_SERIES[@]}"; do
for bs in "${BUNDLED_GO_SERIES[@]}"; do
[[ "$series" == "$bs" ]] && needs_bundled=true
done
done
if $needs_bundled; then
GO_TARBALL="go${BUNDLED_GO_VERSION}.linux-amd64.tar.gz"
if [[ ! -f "${RELEASE_DIR}/${GO_TARBALL}" ]]; then
echo "==> Downloading Go ${BUNDLED_GO_VERSION} toolchain..."
curl -fsSL -o "${RELEASE_DIR}/${GO_TARBALL}" "${BUNDLED_GO_URL}"
fi
fi
PPA_REV=1
PPA_CHANGES_FILES=()
for series in "${PPA_SERIES[@]}"; do
PPA_VERSION="${VERSION}~ppa${PPA_REV}~${series}"
# Check if this series needs bundled Go
use_bundled=false
for bs in "${BUNDLED_GO_SERIES[@]}"; do
[[ "$series" == "$bs" ]] && use_bundled=true
done
if $use_bundled; then
# Bundle Go toolchain into source tree
echo " ${series}: bundling Go ${BUNDLED_GO_VERSION} toolchain..."
rm -rf _go
mkdir -p _go
tar -xzf "${RELEASE_DIR}/${GO_TARBALL}" -C _go --strip-components=1
# Use modified debian/control without golang-go dependency
cat > debian/control <<CTRL
Source: ${NAME}
Section: utils
Priority: optional
Maintainer: ${MAINTAINER}
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.6.2
Homepage: https://github.com/phntom/fastdedup
Vcs-Git: https://github.com/phntom/fastdedup.git
Vcs-Browser: https://github.com/phntom/fastdedup
Package: ${NAME}
Architecture: amd64
Depends: \${shlibs:Depends}, \${misc:Depends}
Description: ${DESC}
fastdedup performs two-pass deduplication on filesystems that support
reflinks (btrfs, XFS, ZFS). It surveys file sizes to identify the
most impactful duplicates, then deduplicates them using reflinks for
instant, copy-on-write deduplication with no extra disk space.
Package: ${NAME}-daily
Architecture: all
Depends: ${NAME}, \${misc:Depends}
Description: Daily automatic file deduplication using reflinks
Installs a daily cron job that runs fastdedup on all mounted btrfs,
XFS, and ZFS filesystems. Configure via /etc/default/fastdedup.
Package: ${NAME}-weekly
Architecture: all
Depends: ${NAME}, \${misc:Depends}
Description: Weekly automatic file deduplication using reflinks
Installs a weekly cron job that runs fastdedup on all mounted btrfs,
XFS, and ZFS filesystems. Configure via /etc/default/fastdedup.
CTRL
# Use modified debian/rules that uses bundled Go
cat > debian/rules <<'RULES'
#!/usr/bin/make -f
export GOROOT := $(CURDIR)/_go
export PATH := $(GOROOT)/bin:$(PATH)
DEB_VERSION := $(shell dpkg-parsechangelog -S Version)
%:
dh $@
override_dh_auto_build:
HOME=$(CURDIR) GOMODCACHE=$(CURDIR)/.gomodcache GOCACHE=$(CURDIR)/.gocache GOTOOLCHAIN=local GOFLAGS=-mod=vendor $(GOROOT)/bin/go build -ldflags="-s -w -X main.version=$(DEB_VERSION)" -o fastdedup .
override_dh_auto_install:
install -D -m 0755 fastdedup debian/fastdedup/usr/bin/fastdedup
install -D -m 0644 debian/fastdedup.default debian/fastdedup/etc/default/fastdedup
install -D -m 0644 debian/fastdedup.logrotate debian/fastdedup/etc/logrotate.d/fastdedup
install -D -m 0755 debian/fastdedup-cron debian/fastdedup-daily/etc/cron.daily/fastdedup
install -D -m 0755 debian/fastdedup-cron debian/fastdedup-weekly/etc/cron.weekly/fastdedup
override_dh_auto_test:
# skip tests for PPA build
override_dh_dwz:
# skip dwz for Go binaries
override_dh_strip:
# skip strip for Go binaries
RULES
chmod +x debian/rules
else
# Restore original debian files for series with system Go
cp "${RELEASE_DIR}/control.saved" debian/control
cp "${RELEASE_DIR}/rules.saved" debian/rules
rm -rf _go
fi
# Update debian/changelog for this series
cat > debian/changelog <<CHLOG
${NAME} (${PPA_VERSION}) ${series}; urgency=low
* Release v${VERSION}
-- ${MAINTAINER} $(date -R)
CHLOG
# Clean previous artifacts for this version
rm -f ../${NAME}_${PPA_VERSION}*
printf " %-12s building..." "$series"
if ! debuild -S -k"${GPG_KEY}" 2>/dev/null; then
echo " FAILED"
# Restore debian files before aborting
cp "${RELEASE_DIR}/control.saved" debian/control
cp "${RELEASE_DIR}/rules.saved" debian/rules
rm -f "${RELEASE_DIR}/control.saved" "${RELEASE_DIR}/rules.saved"
rm -rf _go vendor/
echo "ERROR: PPA source build failed for ${series} — aborting release"
exit 1
fi
echo " ok"
PPA_CHANGES_FILES+=("../${NAME}_${PPA_VERSION}_source.changes")
done
# Restore original debian files and clean up
cp "${RELEASE_DIR}/control.saved" debian/control
cp "${RELEASE_DIR}/rules.saved" debian/rules
rm -f "${RELEASE_DIR}/control.saved" "${RELEASE_DIR}/rules.saved"
rm -rf _go
# Restore changelog to first non-bundled series (or first series)
FIRST_SERIES="${PPA_SERIES[0]}"
cat > debian/changelog <<CHLOG
${NAME} (${VERSION}~ppa${PPA_REV}~${FIRST_SERIES}) ${FIRST_SERIES}; urgency=low
* Release v${VERSION}
-- ${MAINTAINER} $(date -R)
CHLOG
# Clean up vendor dir (it's gitignored)
rm -rf vendor/
# ── All builds succeeded — now tag, push, and upload ───────────────
echo ""
echo "==> All builds successful. Tagging and uploading..."
# Tag
if git rev-parse "v${VERSION}" &>/dev/null; then
echo " Tag v${VERSION} already exists, skipping"
else
echo " Tagging v${VERSION}"
git tag -a "v${VERSION}" -m "Release v${VERSION}"
fi
# Push tag
echo " Pushing tag..."
git push origin "v${VERSION}"
# Upload PPA packages
echo " Uploading PPA packages..."
for changes_file in "${PPA_CHANGES_FILES[@]}"; do
series_name=$(basename "$changes_file" | sed 's/.*~\(.*\)_source.changes/\1/')
printf " %-12s " "$series_name"
if dput --force "${PPA_TARGET}" "$changes_file" 2>/dev/null; then
echo "ok"
else
echo "FAILED (non-fatal)"
fi
done
# ── Summary ─────────────────────────────────────────────────────────
echo ""
echo "==> Release ${VERSION} ready in ${RELEASE_DIR}/"
echo " $(ls -1 "$RELEASE_DIR" | wc -l) files"
echo ""
echo "To publish on GitHub:"
echo " gh release create v${VERSION} ${RELEASE_DIR}/* --title 'v${VERSION}' --notes '## v${VERSION}'"
echo ""
echo "PPA uploads submitted for: ${PPA_SERIES[*]}"
echo " Monitor builds at: https://launchpad.net/~phntm/+archive/ubuntu/ppa"