#!/bin/sh
# Build an uploadable release without local secrets, data or development tools.
set -eu

project_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
cd "$project_dir"
release_name="swedenstart-$(date -u +%Y%m%dT%H%M%SZ)"
output_dir="$project_dir/dist/releases"
mkdir -p "$output_dir"
archive="$output_dir/$release_name.tar.gz"
if [ -e "$archive" ]; then
    echo 'A release with this timestamp already exists. Try again in a moment.' >&2
    exit 1
fi
stage_dir=$(mktemp -d "${TMPDIR:-/tmp}/swedenstart-release.XXXXXX")
trap 'rm -rf "$stage_dir"' EXIT HUP INT TERM
release_dir="$stage_dir/swedenstart"
mkdir "$release_dir"

npm run build

for directory in app config lang resources routes; do
    rsync -a --exclude='.DS_Store' "$directory/" "$release_dir/$directory/"
done
mkdir -p "$release_dir/bootstrap/cache" "$release_dir/database"
cp bootstrap/*.php "$release_dir/bootstrap/"
rsync -a database/migrations database/seeders "$release_dir/database/"
rsync -a --exclude='/hot' --exclude='/storage' --exclude='.DS_Store' public/ "$release_dir/public/"
cp artisan composer.json composer.lock .env.example "$release_dir/"
mkdir "$release_dir/deploy"
cp deploy/production.env.example deploy/crontab.example "$release_dir/deploy/"
mkdir -p "$release_dir/docs"
cp docs/deployment.md docs/nixihost.md docs/asset-sources.md "$release_dir/docs/"
for directory in app/private app/public framework/cache/data framework/sessions framework/views logs; do
    mkdir -p "$release_dir/storage/$directory"
done

cd "$release_dir"
# Install from the lockfile in isolation; do not change the developer's vendor/.
COMPOSER_CACHE_DIR="${COMPOSER_CACHE_DIR:-$stage_dir/composer-cache}"
export COMPOSER_CACHE_DIR
composer install --no-dev --prefer-dist --no-interaction --no-plugins --no-scripts --optimize-autoloader
APP_ENV=production APP_DEBUG=false php artisan package:discover --no-ansi
composer check-platform-reqs --no-dev

php <<'PHP'
<?php
$manifest = [
    'application' => 'SwedenStart',
    'origin' => 'https://www.swedenstart.com',
    'built_at_utc' => gmdate('c'),
    'builder_php' => PHP_VERSION,
    'composer_lock_sha256' => hash_file('sha256', 'composer.lock'),
    'vite_manifest_sha256' => hash_file('sha256', 'public/build/manifest.json'),
    'status' => 'Prepared artifact; hosting and launch checks must pass before public access.',
];
file_put_contents('RELEASE.json', json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n");
$hashes = [];
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS)) as $file) {
    $path = substr($file->getPathname(), 2);
    if ($file->isLink() || preg_match('#(^|/)\.env(\.|$)#', $path) && $path !== '.env.example') {
        throw new RuntimeException('Unexpected link or environment file in release: '.$path);
    }
    if ($file->isFile()) {
        $hashes[$path] = hash_file('sha256', $path).'  '.$path;
    }
}
ksort($hashes);
file_put_contents('SHA256SUMS', implode("\n", $hashes)."\n");
PHP

COPYFILE_DISABLE=1 tar -czf "$archive" -C "$stage_dir" swedenstart
php -r 'file_put_contents($argv[1].".sha256", hash_file("sha256", $argv[1])."  ".basename($argv[1])."\n");' "$archive"
echo "Release: $archive"
echo "Checksum: $archive.sha256"
echo 'Upload outside the web document root. The archive contains no production .env or database.'
