From c00b30a31fac5d49d33e8a80108dc8e9a570a698 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Tue, 9 Jun 2026 09:39:15 +0200 Subject: [PATCH 1/2] fix: export NC in update-version-php + clear shellcheck warnings update-version-php.sh read the target dir via getenv('NC') in its inline PHP but never exported NC, so it always fell back to /tmp/nextcloud regardless of the argument. Export NC so the argument is honoured (and the script is testable against any directory). Also fix the warnings that surfaced once all scripts are shellchecked: - update-version-php.sh: declare/assign BUILD_STRING separately (SC2155) - clean-dev-files.sh: document the intentional glob match (SC2053) - fetch-all.sh: pass composer args via an array instead of word-splitting (SC2086) Signed-off-by: skjnldsv --- .github/scripts/clean-dev-files.sh | 4 +++- .github/scripts/fetch-all.sh | 4 ++-- .github/scripts/update-version-php.sh | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/scripts/clean-dev-files.sh b/.github/scripts/clean-dev-files.sh index 7f82ffacd3b..a8f3d66eed2 100755 --- a/.github/scripts/clean-dev-files.sh +++ b/.github/scripts/clean-dev-files.sh @@ -25,7 +25,9 @@ if [ -f ".nextcloudignore" ]; then clean="${pattern#/}" skip=false for keep in "${KEEP_FILES[@]}"; do - # shellcheck disable=SC2254 + # $clean is an intentional glob pattern (e.g. composer.*) matched against + # the preserved file name, so the RHS must stay unquoted. + # shellcheck disable=SC2053,SC2254 if [[ "$keep" == $clean ]]; then skip=true break diff --git a/.github/scripts/fetch-all.sh b/.github/scripts/fetch-all.sh index 5a2fc86a7cc..8a915433b83 100755 --- a/.github/scripts/fetch-all.sh +++ b/.github/scripts/fetch-all.sh @@ -62,8 +62,8 @@ jq -r '.[] | "\(.id) \(.repo) \(.composer_args // "")"' "$CONFIG" | while read - | length > 0 ' "$OUTPUT/apps/$id/composer.json" > /dev/null 2>&1; then echo " Running composer install for $id" - ARGS="${composer_args:---no-dev -a --quiet}" - (cd "$OUTPUT/apps/$id" && COMPOSER_ALLOW_SUPERUSER=1 composer install $ARGS) + read -r -a ARGS <<< "${composer_args:---no-dev -a --quiet}" + (cd "$OUTPUT/apps/$id" && COMPOSER_ALLOW_SUPERUSER=1 composer install "${ARGS[@]}") fi done diff --git a/.github/scripts/update-version-php.sh b/.github/scripts/update-version-php.sh index 640e7b52590..60b7017c4ae 100755 --- a/.github/scripts/update-version-php.sh +++ b/.github/scripts/update-version-php.sh @@ -9,13 +9,15 @@ set -e -NC="${1:?Usage: update-version-php.sh }" +# NC is exported because the inline PHP below reads it via getenv('NC'). +export NC="${1:?Usage: update-version-php.sh }" export CHANNEL="${2:?Missing channel (stable/beta)}" export BRANCH="${3:?Missing branch (stable34/master)}" COMMIT_HASH=$(cat "$NC/release-commit-hash") rm -f "$NC/release-commit-hash" -export BUILD_STRING="$(date -u +%Y-%m-%dT%H:%M:%S+00:00) ${COMMIT_HASH}" +BUILD_STRING="$(date -u +%Y-%m-%dT%H:%M:%S+00:00) ${COMMIT_HASH}" +export BUILD_STRING # Preserves OC_Version and OC_VersionString from the repo. # Sets channel, build timestamp, edition, and vendor. From e065d17918a1bd7ffce80a4bff510684fa88643b Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Tue, 9 Jun 2026 09:39:15 +0200 Subject: [PATCH 2/2] test: add build-script tests and a global lint workflow The build scripts in .github/scripts/ had no tests and no lint. Add a hermetic harness (tests/build-scripts/) reusing the snapshot pattern: - assemble.sh, clean-dev-files.sh, clean-server-dev-files.sh: run on a fixture tree, snapshot a manifest of the result. - update-version-php.sh: snapshot the rewritten version.php (build date normalized). - package.sh / sign-release.sh / generate-metadata.sh: extract the pure bits (generate_checksums, default_cert, wrap_metadata) behind a "stop when sourced" guard and unit-test them - no sudo, tar/zip, occ or database needed. A new workflow lints every script + harness with shellcheck and runs both suites (offline; PHP only). Behaviour of the extracted scripts is unchanged when executed directly. Signed-off-by: skjnldsv --- .github/scripts/generate-metadata.sh | 38 +++--- .github/scripts/package.sh | 24 ++-- .github/scripts/sign-release.sh | 11 +- .github/workflows/test-build-scripts.yml | 48 ++++++++ tests/build-scripts/run.sh | 114 ++++++++++++++++++ .../scenarios/assemble-basic/args.env | 1 + .../assemble-basic/expected/snapshot | 11 ++ .../fixture/3rdparty/autoload.php | 1 + .../assemble-basic/fixture/apps/news/main.php | 1 + .../fixture/apps/notes/main.php | 1 + .../fixture/docs/Nextcloud_User_Manual.pdf | Bin 0 -> 4 bytes .../fixture/docs/admin_manual/index.html | 1 + .../fixture/docs/user_manual/en/index.html | 1 + .../fixture/example-files/Readme.md | 1 + .../fixture/server/apps/files/appinfo.xml | 1 + .../fixture/server/config/config.php | 1 + .../fixture/server/core/doc/admin/index.php | 1 + .../fixture/server/core/doc/user/index.php | 1 + .../fixture/server/core/skeleton/oldfile.txt | 1 + .../fixture/server/data/.gitkeep | 1 + .../assemble-basic/fixture/server/version.php | 1 + .../assemble-basic/fixture/updater/extra.txt | 1 + .../assemble-basic/fixture/updater/index.php | 1 + .../fixture/updater/updater.phar | 1 + .../scenarios/clean-dev-files-basic/args.env | 1 + .../clean-dev-files-basic/expected/snapshot | 7 ++ .../fixture/.eslintrc.json | 1 + .../fixture/.github/workflow.yml | 1 + .../fixture/.nextcloudignore | 4 + .../clean-dev-files-basic/fixture/Makefile | 1 + .../clean-dev-files-basic/fixture/README.md | 1 + .../fixture/appinfo/info.xml | 1 + .../fixture/composer.json | 1 + .../fixture/composer.lock | 1 + .../clean-dev-files-basic/fixture/debug.log | 1 + .../fixture/js/app.js.map | 1 + .../fixture/js/app.js.map.license | 1 + .../fixture/jsconfig.json | 1 + .../clean-dev-files-basic/fixture/lib/Foo.php | 1 + .../fixture/package-lock.json | 1 + .../fixture/package.json | 1 + .../fixture/screenshots/shot.png | 1 + .../clean-dev-files-basic/fixture/src/main.js | 1 + .../fixture/tests/UnitTest.php | 1 + .../fixture/webpack.config.js | 1 + .../clean-server-dev-files-fallback/args.env | 1 + .../expected/snapshot | 5 + .../fixture/.gitattributes | 1 + .../fixture/.github/ci.yml | 1 + .../fixture/.well-known/carddav | 1 + .../fixture/Makefile | 1 + .../fixture/README.md | 1 + .../fixture/apps/dav/bin/tool | 1 + .../fixture/apps/files/appinfo/info.xml | 1 + .../fixture/apps/testing/app.php | 1 + .../fixture/config/config.php | 1 + .../fixture/cypress.config.ts | 1 + .../fixture/data/.ocdata | 1 + .../fixture/index.php | 1 + .../fixture/js/a.js.map | 1 + .../fixture/js/a.js.map.license | 1 + .../fixture/lib/base.php | 1 + .../fixture/tests/Test.php | 1 + .../fixture/version.php | 1 + .../fixture/webpack.config.js | 1 + .../update-version-php-master/args.env | 3 + .../expected/snapshot | 6 + .../fixture/release-commit-hash | 1 + .../fixture/version.php | 6 + .../update-version-php-stable/args.env | 3 + .../expected/snapshot | 7 ++ .../fixture/release-commit-hash | 1 + .../fixture/version.php | 6 + .../update-version-php-upgradefrom/args.env | 3 + .../expected/snapshot | 11 ++ .../fixture/release-commit-hash | 1 + .../fixture/version.php | 7 ++ tests/build-scripts/unit.sh | 84 +++++++++++++ 78 files changed, 434 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/test-build-scripts.yml create mode 100755 tests/build-scripts/run.sh create mode 100644 tests/build-scripts/scenarios/assemble-basic/args.env create mode 100644 tests/build-scripts/scenarios/assemble-basic/expected/snapshot create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/3rdparty/autoload.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/apps/news/main.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/apps/notes/main.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/docs/Nextcloud_User_Manual.pdf create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/docs/admin_manual/index.html create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/docs/user_manual/en/index.html create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/example-files/Readme.md create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/apps/files/appinfo.xml create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/config/config.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/core/doc/admin/index.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/core/doc/user/index.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/core/skeleton/oldfile.txt create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/data/.gitkeep create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/server/version.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/updater/extra.txt create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/updater/index.php create mode 100644 tests/build-scripts/scenarios/assemble-basic/fixture/updater/updater.phar create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/args.env create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/expected/snapshot create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/.eslintrc.json create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/.github/workflow.yml create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/.nextcloudignore create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/Makefile create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/README.md create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/appinfo/info.xml create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.json create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.lock create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/debug.log create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map.license create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/jsconfig.json create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/lib/Foo.php create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/package-lock.json create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/package.json create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/screenshots/shot.png create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/src/main.js create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/tests/UnitTest.php create mode 100644 tests/build-scripts/scenarios/clean-dev-files-basic/fixture/webpack.config.js create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/args.env create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/expected/snapshot create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/.gitattributes create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/.github/ci.yml create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/.well-known/carddav create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/Makefile create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/README.md create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/apps/dav/bin/tool create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/apps/files/appinfo/info.xml create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/apps/testing/app.php create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/config/config.php create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/cypress.config.ts create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/data/.ocdata create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/index.php create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/js/a.js.map create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/js/a.js.map.license create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/lib/base.php create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/tests/Test.php create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/version.php create mode 100644 tests/build-scripts/scenarios/clean-server-dev-files-fallback/fixture/webpack.config.js create mode 100644 tests/build-scripts/scenarios/update-version-php-master/args.env create mode 100644 tests/build-scripts/scenarios/update-version-php-master/expected/snapshot create mode 100644 tests/build-scripts/scenarios/update-version-php-master/fixture/release-commit-hash create mode 100644 tests/build-scripts/scenarios/update-version-php-master/fixture/version.php create mode 100644 tests/build-scripts/scenarios/update-version-php-stable/args.env create mode 100644 tests/build-scripts/scenarios/update-version-php-stable/expected/snapshot create mode 100644 tests/build-scripts/scenarios/update-version-php-stable/fixture/release-commit-hash create mode 100644 tests/build-scripts/scenarios/update-version-php-stable/fixture/version.php create mode 100644 tests/build-scripts/scenarios/update-version-php-upgradefrom/args.env create mode 100644 tests/build-scripts/scenarios/update-version-php-upgradefrom/expected/snapshot create mode 100644 tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/release-commit-hash create mode 100644 tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/version.php create mode 100755 tests/build-scripts/unit.sh diff --git a/.github/scripts/generate-metadata.sh b/.github/scripts/generate-metadata.sh index 30a84d4399b..06924577bee 100755 --- a/.github/scripts/generate-metadata.sh +++ b/.github/scripts/generate-metadata.sh @@ -8,6 +8,29 @@ set -e +# Wrap the raw migration metadata JSON with build timestamps and write the +# final .metadata file. Reads env: METADATA_FILE, OUTPUT_FILE, BUILD_START, +# BUILD_DURATION. Kept as a function so it can be tested without occ/a database. +wrap_metadata() { + php << 'EOPHP' + (int)getenv('BUILD_START'), + 'duration' => (int)getenv('BUILD_DURATION'), +]; +file_put_contents( + getenv('OUTPUT_FILE'), + json_encode($meta, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) +); +echo "Metadata file created\n"; +EOPHP +} + +# When sourced (tests), stop here after defining functions. +[[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 0 + NC="${1:?Usage: generate-metadata.sh }" VERSION="${2:?Missing version}" OUTPUT_DIR="${3:?Missing output directory}" @@ -41,19 +64,6 @@ export OUTPUT_FILE="$OUTPUT_DIR/nextcloud-${VERSION}.metadata" export BUILD_START="$START_TS" export BUILD_DURATION="$DURATION" -php << 'EOPHP' - (int)getenv('BUILD_START'), - 'duration' => (int)getenv('BUILD_DURATION'), -]; -file_put_contents( - getenv('OUTPUT_FILE'), - json_encode($meta, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) -); -echo "Metadata file created\n"; -EOPHP +wrap_metadata rm -rf "$INSTALL_DIR" /tmp/metadata-raw.json diff --git a/.github/scripts/package.sh b/.github/scripts/package.sh index 888e0f19025..f69a1a56f52 100755 --- a/.github/scripts/package.sh +++ b/.github/scripts/package.sh @@ -9,6 +9,22 @@ set -e +# Generate sha256/sha512/md5 sidecars for the release archives +# (nextcloud-.{tar.bz2,zip}) in . +generate_checksums() { + local output="$1" version="$2" file + for file in "nextcloud-${version}.tar.bz2" "nextcloud-${version}.zip"; do + [ -f "$output/$file" ] || continue + ( cd "$output" \ + && sha256sum "$file" > "${file}.sha256" \ + && sha512sum "$file" > "${file}.sha512" \ + && md5sum "$file" > "${file}.md5" ) + done +} + +# When sourced (tests), stop here after defining functions. +[[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 0 + NC="${1:?Usage: package.sh }" VERSION="${2:?Missing version}" OUTPUT="${3:?Missing output directory}" @@ -33,13 +49,7 @@ echo "Creating zip..." # Generate checksums echo "Generating checksums..." -cd "$OUTPUT" -for file in "nextcloud-${VERSION}.tar.bz2" "nextcloud-${VERSION}.zip"; do - [ -f "$file" ] || continue - sha256sum "$file" > "${file}.sha256" - sha512sum "$file" > "${file}.sha512" - md5sum "$file" > "${file}.md5" -done +generate_checksums "$OUTPUT" "$VERSION" echo "Packages created:" ls -lh "$OUTPUT/nextcloud-${VERSION}"* diff --git a/.github/scripts/sign-release.sh b/.github/scripts/sign-release.sh index b0c74b04773..b3b989db709 100755 --- a/.github/scripts/sign-release.sh +++ b/.github/scripts/sign-release.sh @@ -9,9 +9,18 @@ set -e +# Resolve the signing certificate path: the given one, or the release default. +# Args: [certificate] +default_cert() { + echo "${2:-$1/resources/codesigning/core.crt}" +} + +# When sourced (tests), stop here after defining functions. +[[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 0 + NC="${1:?Usage: sign-release.sh [certificate]}" KEY="${2:?Missing private key path}" -CERT="${3:-$NC/resources/codesigning/core.crt}" +CERT="$(default_cert "$NC" "${3:-}")" chmod 755 "$NC/occ" chmod 777 "$NC/config" diff --git a/.github/workflows/test-build-scripts.yml b/.github/workflows/test-build-scripts.yml new file mode 100644 index 00000000000..d107cf8e4a3 --- /dev/null +++ b/.github/workflows/test-build-scripts.yml @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: Test build scripts + +on: + push: + branches: + - main + paths: + - '.github/scripts/**' + - 'tests/build-scripts/**' + pull_request: + paths: + - '.github/scripts/**' + - 'tests/build-scripts/**' + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + # Global lint of every release script and every test harness. + - name: Shellcheck + run: shellcheck $(find .github/scripts tests -type f -name '*.sh' | sort) + + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Set up PHP + uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2.37.1 + with: + php-version: '8.2' + tools: none + + - name: Run snapshot tests + run: bash tests/build-scripts/run.sh + + - name: Run unit tests + run: bash tests/build-scripts/unit.sh diff --git a/tests/build-scripts/run.sh b/tests/build-scripts/run.sh new file mode 100755 index 00000000000..5df3fc9cbbe --- /dev/null +++ b/tests/build-scripts/run.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT +# +# Snapshot test runner for the release build scripts (assemble.sh, +# clean-dev-files.sh, update-version-php.sh). +# +# These scripts only rearrange/clean a directory tree, so each scenario copies a +# fixture tree, runs the script, and snapshots the result: +# - assemble / clean-dev-files -> a manifest (sorted relative file paths) +# - update-version-php -> the rewritten version.php, build date normalized +# +# Usage: +# run.sh [--update] # --update regenerates expected/ from actual output +# +# Each scenario is a directory under scenarios/ containing: +# args.env - SCRIPT (assemble|clean-dev-files|update-version-php) + extras +# fixture/ - the input tree +# expected/snapshot - the expected manifest or normalized version.php + +set -euo pipefail + +TEST_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_DIR="$(cd "$TEST_DIR/../.." && pwd)" +SCENARIOS_DIR="$TEST_DIR/scenarios" +SCRIPTS="$REPO_DIR/.github/scripts" + +UPDATE_MODE=false +[[ "${1:-}" == "--update" ]] && UPDATE_MODE=true + +PASS=0 +FAIL=0 +ERRORS="" + +# Sorted list of files + symlinks relative to a directory. +manifest() { + (cd "$1" && find . \( -type f -o -type l \) | LC_ALL=C sort) +} + +run_scenario() { + local dir="$1" + local name + name=$(basename "$dir") + echo "--- ${name} ---" + + local SCRIPT CHANNEL BRANCH + SCRIPT="" + CHANNEL="stable" + BRANCH="stable34" + # shellcheck source=/dev/null + source "$dir/args.env" + + local work snapshot + work=$(mktemp -d) + snapshot=$(mktemp) + cp -a "$dir/fixture/." "$work/" + + case "$SCRIPT" in + assemble) + # assemble.sh `cp -a server $OUTPUT` expects OUTPUT not to exist yet. + local outparent out + outparent=$(mktemp -d) + out="$outparent/nextcloud" + bash "$SCRIPTS/assemble.sh" "$work" "$out" > /dev/null + manifest "$out" > "$snapshot" + rm -rf "$outparent" + ;; + clean-dev-files) + bash "$SCRIPTS/clean-dev-files.sh" "$work" > /dev/null + manifest "$work" > "$snapshot" + ;; + clean-server-dev-files) + bash "$SCRIPTS/clean-server-dev-files.sh" "$work" > /dev/null + manifest "$work" > "$snapshot" + ;; + update-version-php) + bash "$SCRIPTS/update-version-php.sh" "$work" "$CHANNEL" "$BRANCH" > /dev/null + # Normalize the non-deterministic build timestamp (commit hash stays). + sed -E "s/(\\\$OC_Build = ')[0-9T:+-]+ /\\1 /" "$work/version.php" > "$snapshot" + ;; + *) + echo " FAIL: unknown SCRIPT '$SCRIPT'" + FAIL=$((FAIL + 1)); ERRORS="${ERRORS}\n ${name}: unknown SCRIPT" + rm -rf "$work" "$snapshot"; return + ;; + esac + + if [[ "$UPDATE_MODE" == "true" ]]; then + mkdir -p "$dir/expected" + cp "$snapshot" "$dir/expected/snapshot" + echo " UPDATED expected snapshot" + PASS=$((PASS + 1)) + elif diff -u "$dir/expected/snapshot" "$snapshot"; then + echo " PASS" + PASS=$((PASS + 1)) + else + echo " FAIL: snapshot differs" + FAIL=$((FAIL + 1)); ERRORS="${ERRORS}\n ${name}" + fi + + rm -rf "$work" "$snapshot" +} + +for scenario in "$SCENARIOS_DIR"/*/; do + [[ -f "$scenario/args.env" ]] || continue + run_scenario "$scenario" +done + +echo "" +echo "=== Results: ${PASS} passed, ${FAIL} failed ===" +if [[ $FAIL -gt 0 ]]; then + echo -e "Failures:${ERRORS}" + exit 1 +fi diff --git a/tests/build-scripts/scenarios/assemble-basic/args.env b/tests/build-scripts/scenarios/assemble-basic/args.env new file mode 100644 index 00000000000..10007cf15ad --- /dev/null +++ b/tests/build-scripts/scenarios/assemble-basic/args.env @@ -0,0 +1 @@ +SCRIPT=assemble diff --git a/tests/build-scripts/scenarios/assemble-basic/expected/snapshot b/tests/build-scripts/scenarios/assemble-basic/expected/snapshot new file mode 100644 index 00000000000..55f5ec72550 --- /dev/null +++ b/tests/build-scripts/scenarios/assemble-basic/expected/snapshot @@ -0,0 +1,11 @@ +./3rdparty/autoload.php +./apps/files/appinfo.xml +./apps/news/main.php +./apps/notes/main.php +./core/doc/admin/index.html +./core/doc/user/index.html +./core/skeleton/Nextcloud Manual.pdf +./core/skeleton/Readme.md +./updater/index.php +./updater/updater.phar +./version.php diff --git a/tests/build-scripts/scenarios/assemble-basic/fixture/3rdparty/autoload.php b/tests/build-scripts/scenarios/assemble-basic/fixture/3rdparty/autoload.php new file mode 100644 index 00000000000..a65b41774ad --- /dev/null +++ b/tests/build-scripts/scenarios/assemble-basic/fixture/3rdparty/autoload.php @@ -0,0 +1 @@ +lib diff --git a/tests/build-scripts/scenarios/assemble-basic/fixture/apps/news/main.php b/tests/build-scripts/scenarios/assemble-basic/fixture/apps/news/main.php new file mode 100644 index 00000000000..587be6b4c3f --- /dev/null +++ b/tests/build-scripts/scenarios/assemble-basic/fixture/apps/news/main.php @@ -0,0 +1 @@ +x diff --git a/tests/build-scripts/scenarios/assemble-basic/fixture/apps/notes/main.php b/tests/build-scripts/scenarios/assemble-basic/fixture/apps/notes/main.php new file mode 100644 index 00000000000..587be6b4c3f --- /dev/null +++ b/tests/build-scripts/scenarios/assemble-basic/fixture/apps/notes/main.php @@ -0,0 +1 @@ +x diff --git a/tests/build-scripts/scenarios/assemble-basic/fixture/docs/Nextcloud_User_Manual.pdf b/tests/build-scripts/scenarios/assemble-basic/fixture/docs/Nextcloud_User_Manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..da0de7e0c4068c4f857052d59f355f6b352c90c2 GIT binary patch literal 4 LcmXR&N#g diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.json b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.json @@ -0,0 +1 @@ +{} diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.lock b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.lock new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/composer.lock @@ -0,0 +1 @@ +{} diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/debug.log b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/debug.log new file mode 100644 index 00000000000..6bfe6b19e37 --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/debug.log @@ -0,0 +1 @@ +log diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map new file mode 100644 index 00000000000..b4a284c5cc8 --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map @@ -0,0 +1 @@ +map diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map.license b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map.license new file mode 100644 index 00000000000..a34b0a77ac7 --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/js/app.js.map.license @@ -0,0 +1 @@ +lic diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/jsconfig.json b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/jsconfig.json new file mode 100644 index 00000000000..587be6b4c3f --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/jsconfig.json @@ -0,0 +1 @@ +x diff --git a/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/lib/Foo.php b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/lib/Foo.php new file mode 100644 index 00000000000..b3d9bbc7f37 --- /dev/null +++ b/tests/build-scripts/scenarios/clean-dev-files-basic/fixture/lib/Foo.php @@ -0,0 +1 @@ + deadbeefcafe1234567890abcdef00112233abcd'; +$vendor = 'nextcloud'; diff --git a/tests/build-scripts/scenarios/update-version-php-master/fixture/release-commit-hash b/tests/build-scripts/scenarios/update-version-php-master/fixture/release-commit-hash new file mode 100644 index 00000000000..f8b699501bb --- /dev/null +++ b/tests/build-scripts/scenarios/update-version-php-master/fixture/release-commit-hash @@ -0,0 +1 @@ +deadbeefcafe1234567890abcdef00112233abcd diff --git a/tests/build-scripts/scenarios/update-version-php-master/fixture/version.php b/tests/build-scripts/scenarios/update-version-php-master/fixture/version.php new file mode 100644 index 00000000000..17d7dd4be31 --- /dev/null +++ b/tests/build-scripts/scenarios/update-version-php-master/fixture/version.php @@ -0,0 +1,6 @@ + deadbeefcafe1234567890abcdef00112233abcd'; +$vendor = 'nextcloud'; diff --git a/tests/build-scripts/scenarios/update-version-php-stable/fixture/release-commit-hash b/tests/build-scripts/scenarios/update-version-php-stable/fixture/release-commit-hash new file mode 100644 index 00000000000..f8b699501bb --- /dev/null +++ b/tests/build-scripts/scenarios/update-version-php-stable/fixture/release-commit-hash @@ -0,0 +1 @@ +deadbeefcafe1234567890abcdef00112233abcd diff --git a/tests/build-scripts/scenarios/update-version-php-stable/fixture/version.php b/tests/build-scripts/scenarios/update-version-php-stable/fixture/version.php new file mode 100644 index 00000000000..17d7dd4be31 --- /dev/null +++ b/tests/build-scripts/scenarios/update-version-php-stable/fixture/version.php @@ -0,0 +1,6 @@ + 33, + 1 => 0, +); +$OC_Build = ' deadbeefcafe1234567890abcdef00112233abcd'; +$vendor = 'nextcloud'; diff --git a/tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/release-commit-hash b/tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/release-commit-hash new file mode 100644 index 00000000000..f8b699501bb --- /dev/null +++ b/tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/release-commit-hash @@ -0,0 +1 @@ +deadbeefcafe1234567890abcdef00112233abcd diff --git a/tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/version.php b/tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/version.php new file mode 100644 index 00000000000..e7f67911982 --- /dev/null +++ b/tests/build-scripts/scenarios/update-version-php-upgradefrom/fixture/version.php @@ -0,0 +1,7 @@ + "$work/nextcloud-9.9.9.tar.bz2" + echo "archive-zip" > "$work/nextcloud-9.9.9.zip" + generate_checksums "$work" "9.9.9" + rc=0 + for ext in sha256 sha512 md5; do + for base in tar.bz2 zip; do + f="$work/nextcloud-9.9.9.${base}.${ext}" + [[ -f "$f" ]] || { echo " FAIL: missing $f"; rc=1; } + done + done + # the recorded sums must verify + ( cd "$work" && sha256sum -c nextcloud-9.9.9.tar.bz2.sha256 >/dev/null 2>&1 ) || { echo " FAIL: sha256 does not verify"; rc=1; } + [[ $rc -eq 0 ]] && echo " ok: checksums written and verify" || true + exit $rc +) && PASS=$((PASS + 1)) || FAIL=$((FAIL + 1)) + +echo "--- sign-release.sh: default_cert ---" +( + set +e + # shellcheck source=/dev/null + source "$SCRIPTS/sign-release.sh" + a=$(default_cert "/tmp/nc") + b=$(default_cert "/tmp/nc" "/custom/my.crt") + [[ "$a" == "/tmp/nc/resources/codesigning/core.crt" ]] || { echo " FAIL: default path wrong: $a"; exit 1; } + [[ "$b" == "/custom/my.crt" ]] || { echo " FAIL: explicit cert wrong: $b"; exit 1; } + echo " ok: cert defaulting" +) && PASS=$((PASS + 1)) || FAIL=$((FAIL + 1)) + +echo "--- generate-metadata.sh: wrap_metadata ---" +( + set +e + # shellcheck source=/dev/null + source "$SCRIPTS/generate-metadata.sh" + work=$(mktemp -d) + echo '{"migrations":["a","b"]}' > "$work/raw.json" + export METADATA_FILE="$work/raw.json" + export OUTPUT_FILE="$work/out.metadata" + export BUILD_START=1000 + export BUILD_DURATION=42 + wrap_metadata >/dev/null + init=$(php -r '$m=json_decode(file_get_contents($argv[1]),true); echo $m["build"]["initiated"];' "$work/out.metadata") + dur=$(php -r '$m=json_decode(file_get_contents($argv[1]),true); echo $m["build"]["duration"];' "$work/out.metadata") + mig=$(php -r '$m=json_decode(file_get_contents($argv[1]),true); echo count($m["migrations"]);' "$work/out.metadata") + [[ "$init" == "1000" ]] || { echo " FAIL: build.initiated=$init"; exit 1; } + [[ "$dur" == "42" ]] || { echo " FAIL: build.duration=$dur"; exit 1; } + [[ "$mig" == "2" ]] || { echo " FAIL: migrations preserved=$mig"; exit 1; } + echo " ok: build stamps added, payload preserved" +) && PASS=$((PASS + 1)) || FAIL=$((FAIL + 1)) + +echo "" +echo "=== Unit results: ${PASS} passed, ${FAIL} failed ===" +[[ $FAIL -eq 0 ]]