Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .docker/web/nextcloud.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
upstream php-handler {
server app:9000;
#server unix:/run/php/php8.2-fpm.sock;
zone php-handler 64k;
resolver 127.0.0.11 valid=10s ipv6=off;
resolver_timeout 5s;
server app:9000 resolve;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
Expand Down
18 changes: 15 additions & 3 deletions .github/actions/build-and-scan/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ runs:
using: composite
steps:
- name: Setup Bats
if: inputs.component == 'app'
uses: bats-core/bats-action@77d6fb60505b4d0d1d73e48bd035b55074bbfb43 # 4.0.0
with:
support-install: false
Expand All @@ -32,6 +31,8 @@ runs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0

# Refresh OS security updates: invalidate the app runtime stage and
# rebuild the small web image so cached apt/apk upgrades cannot go stale.
- name: Build app image (linux/amd64)
if: inputs.component == 'app'
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
Expand All @@ -42,6 +43,7 @@ runs:
build-args: |
NEXTCLOUD_BASE_IMAGE=${{ inputs.nextcloud_base_image }}
tags: scan/app:amd64
no-cache-filters: runtime
cache-from: type=gha,scope=app-${{ inputs.nextcloud_version }}-amd64
cache-to: type=gha,mode=max,scope=app-${{ inputs.nextcloud_version }}-amd64

Expand All @@ -55,6 +57,7 @@ runs:
build-args: |
NEXTCLOUD_BASE_IMAGE=${{ inputs.nextcloud_base_image }}
tags: scan/app:arm64
no-cache-filters: runtime
cache-from: type=gha,scope=app-${{ inputs.nextcloud_version }}-arm64
cache-to: type=gha,mode=max,scope=app-${{ inputs.nextcloud_version }}-arm64

Expand All @@ -66,6 +69,7 @@ runs:
platforms: linux/amd64
load: true
tags: scan/web:amd64
no-cache: true
cache-from: type=gha,scope=web-amd64
cache-to: type=gha,mode=max,scope=web-amd64

Expand All @@ -77,6 +81,7 @@ runs:
platforms: linux/arm64
load: true
tags: scan/web:arm64
no-cache: true
cache-from: type=gha,scope=web-arm64
cache-to: type=gha,mode=max,scope=web-arm64

Expand Down Expand Up @@ -108,11 +113,18 @@ runs:
shell: bash
env:
APP_IMAGE: scan/app:amd64
run: bats tests/app-image.bats
run: make test-app-image

- name: Runtime acceptance app image (linux/arm64)
if: inputs.component == 'app'
shell: bash
env:
APP_IMAGE: scan/app:arm64
run: bats tests/app-image.bats
run: make test-app-image

- name: Runtime acceptance web image (linux/amd64)
if: inputs.component == 'web'
shell: bash
env:
WEB_IMAGE: scan/web:amd64
run: make test-web-image
3 changes: 0 additions & 3 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ jobs:
- name: Run offline regression tests
run: make test-ci-scripts

- name: Test Trivy wrapper
run: bash tests/test-scan-images.sh

- name: ShellCheck image publication scripts
run: |
shellcheck scripts/nextcloud-versions.sh scripts/publish-images.sh \
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ncdd-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
paths:
- 'bin/ncdd'
- 'lib/ncdd-test.sh'
- 'tests/ncdd.bats'
- 'tests/cli/**'
- 'docs/ncdd.md'
- 'AGENTS.md'
- 'Makefile'
Expand All @@ -20,7 +20,7 @@ on:
paths:
- 'bin/ncdd'
- 'lib/ncdd-test.sh'
- 'tests/ncdd.bats'
- 'tests/cli/**'
- 'docs/ncdd.md'
- 'AGENTS.md'
- 'Makefile'
Expand Down Expand Up @@ -48,4 +48,4 @@ jobs:
run: shellcheck -x -P SCRIPTDIR bin/ncdd lib/ncdd-test.sh

- name: Test
run: bats tests/ncdd.bats
run: make test-ncdd
12 changes: 6 additions & 6 deletions .github/workflows/nextcloud-development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ on:
- main
paths:
- '.docker/app/**'
- 'tests/app-image.bats'
- 'tests/app/**'
- 'scripts/scan-images.sh'
- 'trivy.yaml'
- '.github/workflows/nextcloud-development.yml'
- 'scripts/resolve-nextcloud-upstream.sh'
- 'scripts/push-master-architecture.sh'
- 'scripts/publish-master-manifest.sh'
- 'tests/nextcloud-development-image.bats'
- 'tests/development/**'
push:
branches:
- main
paths:
- '.docker/app/**'
- 'tests/app-image.bats'
- 'tests/app/**'
- 'scripts/scan-images.sh'
- 'trivy.yaml'
- '.github/workflows/nextcloud-development.yml'
- 'scripts/resolve-nextcloud-upstream.sh'
- 'scripts/push-master-architecture.sh'
- 'scripts/publish-master-manifest.sh'
- 'tests/nextcloud-development-image.bats'
- 'tests/development/**'
schedule:
- cron: '17 3 * * *'
workflow_dispatch:
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
file-install: false

- name: Test development image scripts
run: bats tests/nextcloud-development-image.bats
run: make test-development-image-scripts

validate:
needs:
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
shell: bash
env:
APP_IMAGE: scan/master:${{ matrix.arch }}
run: bats tests/app-image.bats
run: make test-app-image

- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
Expand Down
21 changes: 12 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ APP_TEST_IMAGE ?= nextcloud-app:acceptance
# Maintainer builds use the latest reviewed upstream base, not the deployment image channel.
APP_BASE_IMAGE ?= $(shell jq -er '.versions[-1].image' .github/nextcloud-supported.json)

.PHONY: up-garages3 down-garages3 bootstrap-garages3 garage-status-garages3 start-garages3 wait-nextcloud-garages3 setup-garages3 test-scan-images test-ci-scripts test-development-image-scripts test-ncdd test-app-image test-current-app-image scan-images
.PHONY: up-garages3 down-garages3 bootstrap-garages3 garage-status-garages3 start-garages3 wait-nextcloud-garages3 setup-garages3 test-scan-images test-ci-scripts test-development-image-scripts test-ncdd test-app-image test-web-image test-current-app-image scan-images

up-garages3:
$(COMPOSE) -f $(GARAGES3_COMPOSE_FILE) up -d garage
Expand All @@ -30,23 +30,26 @@ setup-garages3:
$(MAKE) wait-nextcloud-garages3

test-scan-images:
bash tests/test-scan-images.sh
bats tests/ci/scan-images.bats

# Each Bats suite auto-discovers tests from its category directory.
# New tests do not require any Makefile or CI workflow changes.
test-ci-scripts:
bats tests/check-action-pins.bats \
tests/compose-images.bats \
tests/nextcloud-versions.bats \
tests/publish-images.bats
bats tests/ci/*.bats

test-development-image-scripts:
bats tests/nextcloud-development-image.bats
bats tests/development/*.bats

test-ncdd:
bats tests/ncdd.bats
bats tests/cli/*.bats

test-app-image:
@test -n "$(APP_IMAGE)" || { echo 'Usage: make test-app-image APP_IMAGE=<local-image>' >&2; exit 2; }
APP_IMAGE="$(APP_IMAGE)" bats tests/app-image.bats
APP_IMAGE="$(APP_IMAGE)" bats tests/app/*.bats

test-web-image:
@test -n "$(WEB_IMAGE)" || { echo 'Usage: make test-web-image WEB_IMAGE=<local-image>' >&2; exit 2; }
WEB_IMAGE="$(WEB_IMAGE)" bats tests/web/*.bats

test-current-app-image:
@set -e; \
Expand Down
10 changes: 9 additions & 1 deletion docs/maintenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,23 @@ The repository uses Bash, AWK, `jq`, and Bats rather than a separate Python impl
```bash
make test-ci-scripts
make test-development-image-scripts
bash tests/test-scan-images.sh
make test-ncdd
make test-scan-images
make test-app-image APP_IMAGE=scan/app:amd64
make test-web-image WEB_IMAGE=scan/web:amd64
make test-current-app-image
```

The wiki parser regression tests include real historical snapshots from 2023 to 2026, a malformed revision, overlapping EOL entries, and a release listed before publication. Publication tests simulate Docker calls so they do not push to the registry.

The runtime acceptance test uses an isolated Docker network and PostgreSQL container, verifies Nextcloud installation and `occ` status, and checks the PHP-FPM interface. Test-created resources are cleaned up. CI must run these tests against the images actually built by the workflow.

The Trivy wrapper tests are part of the offline CI suite. Bats tests are grouped into `tests/ci/` (offline checks), `tests/development/`,
`tests/cli/`, `tests/app/`, and `tests/web/`. The Makefile discovers every
`*.bats` file in the corresponding directory. Add tests there without changing
GitHub Actions or maintaining a file list. The app and web suites require
locally built images passed through `APP_IMAGE` and `WEB_IMAGE`.

For YAML syntax, Shell scripts, and publication changes, use `actionlint`, `ShellCheck`, and the Bats suite before requesting review. Do not weaken vulnerability gates to pass CI.

## Other maintenance decisions
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bats

setup() {
cd "$BATS_TEST_DIRNAME/.."
cd "$BATS_TEST_DIRNAME/../.."
}

check_pins() {
Expand Down
2 changes: 1 addition & 1 deletion tests/compose-images.bats → tests/ci/compose-images.bats
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bats

setup() {
REPO_ROOT=$(cd "$BATS_TEST_DIRNAME/.." && pwd)
REPO_ROOT=$(cd "$BATS_TEST_DIRNAME/../.." && pwd)
}

assert_published_images() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bats
# Offline regression tests for the official wiki and reviewed JSON format.
setup() {
cd "$BATS_TEST_DIRNAME/.."
cd "$BATS_TEST_DIRNAME/../.."
TEST_ROOT=$(mktemp -d)
export TEST_ROOT
mkdir -p "$TEST_ROOT/bin"
Expand Down
2 changes: 1 addition & 1 deletion tests/publish-images.bats → tests/ci/publish-images.bats
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bats
# Docker is mocked; these tests never push real images to a registry.
setup() {
cd "$BATS_TEST_DIRNAME/.."
cd "$BATS_TEST_DIRNAME/../.."
TEST_ROOT=$(mktemp -d)
export TEST_ROOT
mkdir -p "$TEST_ROOT/bin"
Expand Down
96 changes: 96 additions & 0 deletions tests/ci/scan-images.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bats

setup() {
repo_root="$(cd "$BATS_TEST_DIRNAME/../.." && pwd)"
tmp_root="$(mktemp -d)"
bin_dir="$tmp_root/bin"
report_dir="$tmp_root/reports"
log_file="$tmp_root/trivy.log"
mkdir -p "$bin_dir" "$report_dir"

cat > "$bin_dir/trivy" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail

args=("$@")
platform=''
image=''
output=''
format=''
for ((i = 0; i < ${#args[@]}; i++)); do
case "${args[$i]}" in
--platform)
((i + 1 < ${#args[@]})) || exit 90
platform="${args[$((i + 1))]}"
;;
--format)
((i + 1 < ${#args[@]})) || exit 91
format="${args[$((i + 1))]}"
;;
--output)
((i + 1 < ${#args[@]})) || exit 92
output="${args[$((i + 1))]}"
;;
esac
done
image="${args[-1]}"

printf '%s|%s|%s\n' "$platform" "$format" "$image" >> "$TRIVY_TEST_LOG"

if [[ "$platform" != "$TRIVY_EXPECTED_PLATFORM" ]]; then
printf 'unexpected platform: %s\n' "$platform" >&2
exit 93
fi

if [[ "$format" == sarif ]]; then
[[ -n "$output" ]] || exit 94
printf '{"version":"2.1.0"}\n' > "$output"
fi

if [[ -n "${TRIVY_FAIL_IMAGE:-}" && "$image" == "$TRIVY_FAIL_IMAGE" ]]; then
exit 1
fi
MOCK
chmod +x "$bin_dir/trivy"

export TRIVY_BIN="$bin_dir/trivy"
export TRIVY_TEST_LOG="$log_file"
export TRIVY_REPORT_DIR="$report_dir"
}

teardown() {
rm -rf "$tmp_root"
}

@test "amd64 scans produce table and SARIF results" {
export TRIVY_EXPECTED_PLATFORM=linux/amd64
run bash "$repo_root/scripts/scan-images.sh" 'app@linux/amd64=example/app:amd64'
[ "$status" -eq 0 ]
[ -f "$report_dir/app-linux-amd64.sarif" ]
grep -Fqx 'linux/amd64|table|example/app:amd64' "$log_file"
grep -Fqx 'linux/amd64|sarif|example/app:amd64' "$log_file"
}

@test "arm64 scans produce table and SARIF results" {
export TRIVY_EXPECTED_PLATFORM=linux/arm64
run bash "$repo_root/scripts/scan-images.sh" 'app@linux/arm64=example/app:arm64'
[ "$status" -eq 0 ]
[ -f "$report_dir/app-linux-arm64.sarif" ]
grep -Fqx 'linux/arm64|table|example/app:arm64' "$log_file"
grep -Fqx 'linux/arm64|sarif|example/app:arm64' "$log_file"
}

@test "a Trivy failure blocks the security scan" {
export TRIVY_EXPECTED_PLATFORM=linux/arm64
export TRIVY_FAIL_IMAGE=example/app:arm64
run bash "$repo_root/scripts/scan-images.sh" 'app-failure@linux/arm64=example/app:arm64'
[ "$status" -ne 0 ]
}

@test "unsupported architectures are rejected before invoking Trivy" {
export TRIVY_EXPECTED_PLATFORM=linux/amd64
run bash "$repo_root/scripts/scan-images.sh" 'app@linux/s390x=example/app:amd64'
[ "$status" -ne 0 ]
[[ "$output" == *"Unsupported platform"* ]]
[ ! -s "$log_file" ]
}
2 changes: 1 addition & 1 deletion tests/ncdd.bats → tests/cli/ncdd.bats
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bats

setup() {
REPO_ROOT=$(cd "$BATS_TEST_DIRNAME/.." && pwd)
REPO_ROOT=$(cd "$BATS_TEST_DIRNAME/../.." && pwd)
TMP_ROOT=$(mktemp -d)
mkdir -p "$TMP_ROOT/bin"
export NCDD_TEST_LOG="$TMP_ROOT/docker.log"
Expand Down
Loading
Loading