Skip to content

Commit 31d673c

Browse files
Add locking, output-dir, and install-smoke to build flow
1 parent bff939d commit 31d673c

3 files changed

Lines changed: 100 additions & 7 deletions

File tree

pkg_build.sh

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,24 @@ version="${today_version}.01"
88
plgfile="$CWD/folderview.plus.plg"
99
xmlfile="$CWD/folderview.plus.xml"
1010
release_guard_script="$CWD/scripts/release_guard.sh"
11+
install_smoke_script="$CWD/scripts/install_smoke.sh"
1112
archive_prefix="folderview.plus"
13+
archive_dir="$CWD/archive"
1214
icon_ext_regex='^(png|jpg|jpeg|gif|webp|svg|bmp|ico|avif)$'
1315
validate_after_build=true
1416
dry_run=false
17+
run_install_smoke=false
1518
tmpdir=""
19+
lockfile="$CWD/tmp/pkg_build.lock"
20+
lockdir=""
1621

1722
print_usage() {
1823
cat <<'EOF'
1924
Usage: pkg_build.sh [options]
2025
--beta [N] Build beta package version (YYYY.MM.DD-beta or -betaN)
2126
--dry-run Show computed version/output paths without writing files
27+
--output-dir D Write .txz/.sha256 to directory D (default: ./archive)
28+
--install-smoke Run scripts/install_smoke.sh after successful build
2229
--validate Run scripts/release_guard.sh after build (default: enabled)
2330
--no-validate Skip post-build release guard validation
2431
-h, --help Show this help
@@ -43,6 +50,41 @@ cleanup_tmpdir() {
4350
if [ -n "${tmpdir:-}" ] && [ -d "${tmpdir}" ]; then
4451
rm -rf "${tmpdir}"
4552
fi
53+
if [ -n "${lockdir:-}" ] && [ -d "${lockdir}" ]; then
54+
rm -rf "${lockdir}"
55+
fi
56+
}
57+
58+
ensure_repo_layout() {
59+
if [ ! -f "$plgfile" ]; then
60+
echo "ERROR: Run pkg_build.sh from repo root (missing $plgfile)." >&2
61+
exit 1
62+
fi
63+
if [ ! -f "$xmlfile" ]; then
64+
echo "ERROR: Missing CA template file: $xmlfile" >&2
65+
exit 1
66+
fi
67+
if [ ! -d "$CWD/src/folderview.plus" ]; then
68+
echo "ERROR: Missing plugin source directory: $CWD/src/folderview.plus" >&2
69+
exit 1
70+
fi
71+
}
72+
73+
acquire_build_lock() {
74+
mkdir -p "$CWD/tmp"
75+
if command -v flock >/dev/null 2>&1; then
76+
exec 9>"$lockfile"
77+
if ! flock -n 9; then
78+
echo "ERROR: Another pkg_build.sh instance is already running (lock: $lockfile)." >&2
79+
exit 1
80+
fi
81+
return
82+
fi
83+
lockdir="${lockfile}.d"
84+
if ! mkdir "$lockdir" 2>/dev/null; then
85+
echo "ERROR: Another pkg_build.sh instance is already running (lock: $lockdir)." >&2
86+
exit 1
87+
fi
4688
}
4789

4890
is_stable_version() {
@@ -113,7 +155,7 @@ highest_stable_archive_version_for_date() {
113155
local versions=()
114156
local archive
115157
shopt -s nullglob
116-
for archive in "$CWD/archive/$archive_prefix-"*.txz; do
158+
for archive in "$archive_dir/$archive_prefix-"*.txz; do
117159
local name="${archive##*/}"
118160
local ver="${name#${archive_prefix}-}"
119161
ver="${ver%.txz}"
@@ -183,6 +225,20 @@ while [[ $# -gt 0 ]]; do
183225
--dry-run)
184226
dry_run=true
185227
;;
228+
--output-dir)
229+
if [ -z "${2:-}" ]; then
230+
echo "ERROR: --output-dir requires a path." >&2
231+
exit 1
232+
fi
233+
archive_dir="${2:-}"
234+
shift
235+
;;
236+
--install-smoke)
237+
run_install_smoke=true
238+
;;
239+
--no-install-smoke)
240+
run_install_smoke=false
241+
;;
186242
--validate)
187243
validate_after_build=true
188244
;;
@@ -202,6 +258,14 @@ while [[ $# -gt 0 ]]; do
202258
shift
203259
done
204260

261+
if [[ "$archive_dir" != /* && ! "$archive_dir" =~ ^[A-Za-z]:[\\/].* ]]; then
262+
archive_dir="$CWD/$archive_dir"
263+
fi
264+
265+
ensure_repo_layout
266+
trap cleanup_tmpdir EXIT
267+
acquire_build_lock
268+
205269
require_commands tar sha256sum md5sum sed find date awk grep cp chmod mkdir rm mktemp sort tail
206270
if [ "$validate_after_build" = true ]; then
207271
require_commands bash
@@ -210,6 +274,13 @@ if [ "$validate_after_build" = true ]; then
210274
exit 1
211275
fi
212276
fi
277+
if [ "$run_install_smoke" = true ]; then
278+
require_commands bash
279+
if [ ! -f "$install_smoke_script" ]; then
280+
echo "ERROR: Missing install smoke script: $install_smoke_script" >&2
281+
exit 1
282+
fi
283+
fi
213284

214285
# Set branch and base version by build type
215286
if [ "$BETA" = true ]; then
@@ -247,14 +318,14 @@ elif [ "$BETA" = false ]; then
247318
version="$(next_stable_version_for_date "$today_version")"
248319
fi
249320

250-
filename="$CWD/archive/$archive_prefix-$version.txz"
321+
filename="$archive_dir/$archive_prefix-$version.txz"
251322
if [ -n "$version_override" ] && [ -f "$filename" ]; then
252323
echo "Archive already exists for overridden version: $filename" >&2
253324
exit 1
254325
fi
255326
while [ -f "$filename" ]; do
256327
version="$(next_patch_version "$version")"
257-
filename="$CWD/archive/$archive_prefix-$version.txz"
328+
filename="$archive_dir/$archive_prefix-$version.txz"
258329
done
259330

260331
xml_date=""
@@ -266,18 +337,20 @@ if [ "$dry_run" = true ]; then
266337
echo "Dry run: no files will be written."
267338
echo "Version: $version"
268339
echo "Branch: $branch"
340+
echo "Output directory: $archive_dir"
269341
echo "Archive target: $filename"
270342
echo "PLG file: $plgfile"
271343
if [ -n "$xml_date" ]; then
272344
echo "CA template date: $xml_date"
273345
fi
274346
echo "Post-build validation: $validate_after_build"
347+
echo "Install smoke: $run_install_smoke"
275348
exit 0
276349
fi
277350

278351
mkdir -p "$CWD/tmp"
352+
mkdir -p "$archive_dir"
279353
tmpdir="$(mktemp -d "$CWD/tmp/build.XXXXXX")"
280-
trap cleanup_tmpdir EXIT
281354

282355
cd "$CWD/src/folderview.plus"
283356
while IFS= read -r -d '' file; do
@@ -291,7 +364,12 @@ done < <(find . -type f ! \( -iname "pkg_build.sh" -o -iname "sftp-config.json"
291364
chmod -R 0755 "$tmpdir"
292365

293366
cd "$tmpdir"
294-
tar -cJf "$filename" *
367+
tar --sort=name \
368+
--mtime='UTC 1970-01-01' \
369+
--owner=0 \
370+
--group=0 \
371+
--numeric-owner \
372+
-cJf "$filename" *
295373

296374
cd "$CWD"
297375
md5=$(md5sum "$filename" | awk '{print $1}')
@@ -318,7 +396,10 @@ sed -i 's|/main/folderview.plus.plg|/'"$branch"'/folderview.plus.plg|' "$plgfile
318396
sed -i 's|/main/archive/|/'"$branch"'/archive/|' "$plgfile"
319397

320398
if [ "$validate_after_build" = true ]; then
321-
bash "$release_guard_script"
399+
FVPLUS_ARCHIVE_DIR="$archive_dir" bash "$release_guard_script"
400+
fi
401+
if [ "$run_install_smoke" = true ]; then
402+
bash "$install_smoke_script"
322403
fi
323404

324405
echo "Package created: $filename"

scripts/release_guard.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ PLG_FILE="${ROOT_DIR}/folderview.plus.plg"
66
CA_TEMPLATE_FILE="${ROOT_DIR}/folderview.plus.xml"
77
PLUGIN_SRC_DIR="${ROOT_DIR}/src/folderview.plus/usr/local/emhttp/plugins/folderview.plus"
88
SERVER_DIR="${PLUGIN_SRC_DIR}/server"
9+
ARCHIVE_DIR="${FVPLUS_ARCHIVE_DIR:-${ROOT_DIR}/archive}"
910
MAX_ARCHIVE_BYTES="${FVPLUS_MAX_ARCHIVE_BYTES:-52428800}" # 50 MiB default ceiling
1011
MAX_ARCHIVE_FILE_COUNT="${FVPLUS_MAX_ARCHIVE_FILE_COUNT:-10000}"
1112

@@ -73,7 +74,7 @@ else
7374
' "${PLG_FILE}"
7475
fi
7576

76-
ARCHIVE_FILE="${ROOT_DIR}/archive/folderview.plus-${VERSION}.txz"
77+
ARCHIVE_FILE="${ARCHIVE_DIR}/folderview.plus-${VERSION}.txz"
7778
if [[ ! -f "${ARCHIVE_FILE}" ]]; then
7879
echo "ERROR: Missing archive package for current version: ${ARCHIVE_FILE}" >&2
7980
exit 1

tests/versioning-guard.test.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,18 @@ test('pkg_build includes dependency preflight, safe temp cleanup, dry-run, and c
4040
assert.match(pkgBuild, /require_commands tar sha256sum md5sum sed find date awk grep cp chmod mkdir rm mktemp sort tail/);
4141
assert.match(pkgBuild, /tmpdir="\$\(mktemp -d \"\$CWD\/tmp\/build\.XXXXXX\"\)"/);
4242
assert.match(pkgBuild, /trap cleanup_tmpdir EXIT/);
43+
assert.match(pkgBuild, /ensure_repo_layout/);
44+
assert.match(pkgBuild, /acquire_build_lock/);
45+
assert.match(pkgBuild, /flock -n 9/);
46+
assert.match(pkgBuild, /--output-dir D/);
47+
assert.match(pkgBuild, /--install-smoke/);
4348
assert.match(pkgBuild, /--dry-run/);
4449
assert.match(pkgBuild, /Post-build validation: \$validate_after_build/);
50+
assert.match(pkgBuild, /Install smoke: \$run_install_smoke/);
51+
assert.match(pkgBuild, /--sort=name/);
52+
assert.match(pkgBuild, /--mtime='UTC 1970-01-01'/);
53+
assert.match(pkgBuild, /FVPLUS_ARCHIVE_DIR="\$archive_dir" bash "\$release_guard_script"/);
54+
assert.match(pkgBuild, /bash "\$install_smoke_script"/);
4555
assert.match(pkgBuild, /sha256=\$\(sha256sum "\$filename" \| awk '\{print \$1\}'\)/);
4656
assert.match(pkgBuild, /printf '%s %s\\n' "\$sha256" "\$\(basename "\$filename"\)" > "\$sha256_file"/);
4757
assert.doesNotMatch(pkgBuild, /rm -R "\$CWD\/tmp"/);
@@ -60,6 +70,7 @@ test('release_guard enforces category-signaling changelog content for current ve
6070
});
6171

6272
test('release_guard enforces archive size, file-count, and extension policy', () => {
73+
assert.match(releaseGuard, /ARCHIVE_DIR="\$\{FVPLUS_ARCHIVE_DIR:-\$\{ROOT_DIR\}\/archive\}"/);
6374
assert.match(releaseGuard, /MAX_ARCHIVE_BYTES="\$\{FVPLUS_MAX_ARCHIVE_BYTES:-52428800\}"/);
6475
assert.match(releaseGuard, /MAX_ARCHIVE_FILE_COUNT="\$\{FVPLUS_MAX_ARCHIVE_FILE_COUNT:-10000\}"/);
6576
assert.match(releaseGuard, /Archive exceeds size budget/);

0 commit comments

Comments
 (0)