diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 870f2a18..45643632 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -217,10 +217,9 @@ jobs: /bin/bash -c "./manage.py createdevdata" - name: Collect logs on failure - if: ${{ failure() && matrix.stack }} + if: ${{ failure() }} run: | - docker compose --file="$COMPOSE_FILE_DEV" logs django - docker compose --file="$COMPOSE_FILE_DEV" logs node + docker compose --file="$COMPOSE_FILE_PROD" logs django cleanup: name: Cleanup diff --git a/ci/scripts/restoredb.sh b/ci/scripts/restoredb.sh index f7b4501c..c6f37cf6 100755 --- a/ci/scripts/restoredb.sh +++ b/ci/scripts/restoredb.sh @@ -7,7 +7,8 @@ set -euo pipefail # Honour the engine chosen by the justfile; fall back to docker standalone. COMPOSE="${COMPOSE:-docker compose}" -BRANCH="$(git rev-parse --abbrev-ref HEAD)" +# `/` in a branch name would otherwise become a directory in the dump path. +BRANCH="$(git rev-parse --abbrev-ref HEAD | tr / -)" FOLDER="db-snapshots" OWNER="postgres" DBNAME="securedropdb" @@ -26,10 +27,12 @@ if [ -z "$FILE" ]; then fi echo "Restoring from: $FILE" -# Terminate all other connections -$COMPOSE exec -T "$CONTAINER" psql -o /dev/null -h localhost "$OWNER" postgres \ +# Terminate all other connections. The maintenance commands connect over the +# container's unix socket, which the postgres image trusts; `$OWNER` is the +# superuser this compose stack creates. +$COMPOSE exec -T "$CONTAINER" psql -o /dev/null -U "$OWNER" postgres \ -c "ALTER DATABASE $DBNAME CONNECTION LIMIT 1;" -$COMPOSE exec -T "$CONTAINER" psql -o /dev/null -h localhost "$OWNER" postgres \ +$COMPOSE exec -T "$CONTAINER" psql -o /dev/null -U "$OWNER" postgres \ -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DBNAME';" # `set -e` aborts here if the drop fails, replacing the previous explicit @@ -39,5 +42,8 @@ $COMPOSE exec -T "$CONTAINER" dropdb -U "$OWNER" "$DBNAME" $COMPOSE exec -T "$CONTAINER" createdb -U "$OWNER" --encoding UTF8 \ --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8 --template=template0 \ --owner "$OWNER" "$DBNAME" +# No `-n public`: this schema depends on the `hstore` extension, and extensions +# carry no schema in the dump's TOC, so a schema filter would drop the +# CREATE EXTENSION the restore then trips over. $COMPOSE exec -T "$CONTAINER" pg_restore -U "$OWNER" -1 --no-owner \ - --role="$OWNER" -n public --dbname="$DBNAME" < "$FILE" + --role="$OWNER" --dbname="$DBNAME" < "$FILE" diff --git a/ci/scripts/savedb.sh b/ci/scripts/savedb.sh index 1d17d45c..9247858c 100755 --- a/ci/scripts/savedb.sh +++ b/ci/scripts/savedb.sh @@ -7,7 +7,8 @@ set -euo pipefail # Honour the engine chosen by the justfile; fall back to docker standalone. COMPOSE="${COMPOSE:-docker compose}" -BRANCH="$(git rev-parse --abbrev-ref HEAD)" +# `/` in a branch name would otherwise become a directory in the dump path. +BRANCH="$(git rev-parse --abbrev-ref HEAD | tr / -)" DATE="$(date +%Y-%m-%d-%H-%M-%S)" DUMPFILE="sdo-$BRANCH.$DATE.dump" DBNAME="securedropdb" diff --git a/justfile b/justfile index 17acfe91..140eda2f 100644 --- a/justfile +++ b/justfile @@ -34,7 +34,7 @@ env-check: [ -f .env ] || echo "UID=$(id -u)" > .env # Run the webapp locally, via containers (--build keeps images in sync with the Containerfile). -dev: dev-init +dev: env-check {{compose}} up --build alias compose := dev @@ -102,7 +102,7 @@ pip-compile-dev *FLAGS: (_pip-lock "dev-requirements.txt" "dev-requirements.in" # the builder runs as root, so without it a developer is left with root-owned # requirements files in their checkout. _pip-lock outfile infile *FLAGS: - {{engine}} run --rm -v "{{justfile_directory()}}:/code" -w /code {{python_builder}} \ + {{engine}} run --rm -v "{{justfile_directory()}}:/code:z" -w /code {{python_builder}} \ bash -c 'apt-get update && apt-get install -y --no-install-recommends gcc libpq-dev && \ pip install pip-tools=={{pip_tools_version}} && \ pip-compile --generate-hashes --no-header --allow-unsafe {{FLAGS}} \