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
4 changes: 4 additions & 0 deletions .github/workflows/ncdd-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ on:
- 'AGENTS.md'
- 'Makefile'
- '.github/workflows/ncdd-cli.yml'
- '.github/workflows/test-nextcloud-app.yml'
- 'templates/workflows/ncdd-tests.yml'
- '.github/workflows/test-nextcloud-app.yml'
- 'templates/workflows/ncdd-tests.yml'
push:
branches:
- main
Expand Down
172 changes: 172 additions & 0 deletions .github/workflows/test-nextcloud-app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
name: Test Nextcloud app with NCDD

on:
workflow_call:
inputs:
suite:
description: 'Test suite to run: phpunit or behat'
required: false
default: phpunit
type: string
target:
description: Optional single test target passed to the selected runner
required: false
default: ''
type: string
ref:
description: Optional app ref to test; defaults to the caller SHA
required: false
default: ''
type: string
app_id:
description: Nextcloud app id; defaults to the caller repository name
required: false
default: ''
type: string
ncdd_ref:
description: nextcloud-docker ref containing the NCDD runtime
required: false
default: main
type: string
composer_install:
description: Install Composer dependencies before starting tests
required: false
default: true
type: boolean

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout NCDD
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: LibreCodeCoop/nextcloud-docker
ref: ${{ inputs.ncdd_ref }}
path: .ncdd-runtime
persist-credentials: false

- name: Resolve test contract
id: contract
shell: bash
env:
INPUT_APP_ID: ${{ inputs.app_id }}
INPUT_SUITE: ${{ inputs.suite }}
run: |
set -euo pipefail

app_id="${INPUT_APP_ID:-${GITHUB_REPOSITORY#*/}}"
if [[ ! "${app_id}" =~ ^[A-Za-z0-9._-]+$ ]]; then
echo "Invalid Nextcloud app id: ${app_id}" >&2
exit 2
fi

case "${INPUT_SUITE}" in
phpunit|behat) ;;
*)
echo "Unsupported NCDD suite: ${INPUT_SUITE}" >&2
exit 2
;;
esac

echo "app_id=${app_id}" >> "${GITHUB_OUTPUT}"
echo "app_path=.ncdd-runtime/volumes/nextcloud/apps-extra/${app_id}" >> "${GITHUB_OUTPUT}"

- name: Checkout app
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ github.repository }}
ref: ${{ inputs.ref != '' && inputs.ref || github.sha }}
path: ${{ steps.contract.outputs.app_path }}
persist-credentials: false

- name: Prepare NCDD CI environment
shell: bash
working-directory: .ncdd-runtime
run: |
set -euo pipefail
cp .env.example .env
sed -i \
-e 's/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=nextcloud/' \
-e 's/^NEXTCLOUD_ADMIN_USER=.*/NEXTCLOUD_ADMIN_USER=admin/' \
-e 's/^NEXTCLOUD_ADMIN_PASSWORD=.*/NEXTCLOUD_ADMIN_PASSWORD=admin/' \
-e 's/^NEXTCLOUD_TRUSTED_DOMAINS=.*/NEXTCLOUD_TRUSTED_DOMAINS=web localhost/' \
-e 's/^TZ=.*/TZ=UTC/' \
.env
{
echo 'POSTGRES_DB=nextcloud'
echo 'POSTGRES_USER=nextcloud'
} >> .env

- name: Install Composer dependencies
if: ${{ inputs.composer_install }}
shell: bash
working-directory: ${{ steps.contract.outputs.app_path }}
env:
SUITE: ${{ inputs.suite }}
run: |
set -euo pipefail
command -v composer >/dev/null 2>&1 || {
echo 'Composer is required when composer_install is enabled.' >&2
exit 2
}

composer install --no-interaction --prefer-dist

if [ "${SUITE}" = behat ] && [ -f tests/integration/composer.json ]; then
composer --working-dir=tests/integration install --no-interaction --prefer-dist
fi

- name: Start NCDD
shell: bash
run: bash .ncdd-runtime/bin/ncdd up

- name: Wait for Nextcloud
shell: bash
run: |
set -euo pipefail
for attempt in $(seq 1 90); do
if bash .ncdd-runtime/bin/ncdd doctor --json; then
exit 0
fi
sleep 2
done
bash .ncdd-runtime/bin/ncdd doctor --json || true
exit 1

- name: Enable app
shell: bash
env:
APP_ID: ${{ steps.contract.outputs.app_id }}
run: bash .ncdd-runtime/bin/ncdd exec --as runtime -- php occ app:enable "${APP_ID}"

- name: Run app tests
shell: bash
env:
APP_ID: ${{ steps.contract.outputs.app_id }}
SUITE: ${{ inputs.suite }}
TARGET: ${{ inputs.target }}
run: |
set -euo pipefail
args=(test "${SUITE}" --app "${APP_ID}")
if [ -n "${TARGET}" ]; then
args+=(-- "${TARGET}")
fi
bash .ncdd-runtime/bin/ncdd "${args[@]}"

- name: Show NCDD diagnostics
if: failure()
shell: bash
run: |
bash .ncdd-runtime/bin/ncdd doctor --json || true
bash .ncdd-runtime/bin/ncdd logs app postgres || true

- name: Stop NCDD
if: always()
shell: bash
run: bash .ncdd-runtime/bin/ncdd down -v || true
4 changes: 4 additions & 0 deletions bin/ncdd
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Commands:
up Start the existing NCDD stack
down Stop the existing NCDD stack
status Show stack status
logs [SERVICE...] Show stack logs without ANSI colors
env Show resolved NCDD environment
doctor [--json] Check Docker, Compose, app service, and Nextcloud
shell [--as USER] Open a shell in the app container
Expand Down Expand Up @@ -161,6 +162,9 @@ case "$command" in
status)
compose ps "$@"
;;
logs)
compose logs --no-color "$@"
;;
shell)
user=root
if [ "${1:-}" = "--as" ]; then
Expand Down
37 changes: 36 additions & 1 deletion docs/ncdd.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The Makefile remains focused on repository maintenance tasks. It only exposes `t
```bash
bin/ncdd up
bin/ncdd status
bin/ncdd logs app
bin/ncdd doctor
bin/ncdd doctor --json
bin/ncdd shell
Expand All @@ -28,6 +29,8 @@ bin/ncdd down

`runtime` resolves to `www-data` by default and can be overridden with `NCDD_RUNTIME_USER`.

Use `bin/ncdd logs` for diagnostics instead of rebuilding the underlying Compose command. Optional service names are passed through to Compose.

## Git and app source

NCDD does not fetch application repositories and does not receive GitHub credentials. Human users, CI, and agents perform the checkout outside the containers.
Expand Down Expand Up @@ -74,4 +77,36 @@ The initial API intentionally supports only PHPUnit and Behat. Frontend runners,

## Configuration policy

NCDD still does not introduce `.ncdd.yml`. Test behavior uses explicit CLI arguments and narrowly scoped environment variables so the repository does not acquire a second configuration model before it is necessary.
NCDD still does not introduce `.ncdd.yml`. Test behavior uses explicit CLI arguments and narrowly scoped environment variables so the repository does not acquire a second configuration model before it is necessary.

## GitHub Actions consumer workflow

The reusable workflow `.github/workflows/test-nextcloud-app.yml` lets an app repository run the same NCDD test contract in GitHub Actions.

It intentionally follows the current NCDD scope:

- PHPUnit and Behat only;
- the app is checked out under `volumes/nextcloud/apps-extra/<app-id>`;
- no `.ncdd.yml`;
- no alternate Compose stack;
- no scenario or frontend mini-framework.

A consumer can call it with:

```yaml
jobs:
ncdd:
uses: LibreCodeCoop/nextcloud-docker/.github/workflows/test-nextcloud-app.yml@main
with:
suite: phpunit
```

`app_id` defaults to the caller repository name and can be overridden when the repository name differs from the Nextcloud app id. `target` is a single runner argument and is passed without shell evaluation.

The workflow can install Composer dependencies before starting NCDD. This bootstrap runs in the GitHub-hosted workspace, while Nextcloud and the selected test runner execute through NCDD. Set `composer_install: false` when the caller provides dependencies by another mechanism.

The workflow uses the Nextcloud version already defined by this repository. It does not introduce a second Nextcloud version input.

A ready-to-copy caller example is available at `templates/workflows/ncdd-tests.yml`.

Dev Containers and Codespaces are deliberately outside this increment. They should only be added after the reusable CI contract has been exercised by a real app repository.
28 changes: 28 additions & 0 deletions templates/workflows/ncdd-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: NCDD app tests

on:
pull_request:
workflow_dispatch:
inputs:
suite:
description: Test suite
required: true
default: phpunit
type: choice
options:
- phpunit
- behat
target:
description: Optional single test target
required: false
type: string

permissions:
contents: read

jobs:
ncdd:
uses: LibreCodeCoop/nextcloud-docker/.github/workflows/test-nextcloud-app.yml@main
with:
suite: ${{ inputs.suite || 'phpunit' }}
target: ${{ inputs.target || '' }}
8 changes: 7 additions & 1 deletion tests/ncdd.bats
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ teardown() {
grep -q 'up -d redis postgres app web cron' "$NCDD_TEST_LOG"
}

@test "logs uses the existing compose stack" {
run bash "$REPO_ROOT/bin/ncdd" logs app
[ "$status" -eq 0 ]
grep -q -- 'logs --no-color app' "$NCDD_TEST_LOG"
}

@test "agent help keeps Docker Compose as an implementation detail" {
run bash "$REPO_ROOT/bin/ncdd" help ai
[ "$status" -eq 0 ]
Expand Down Expand Up @@ -108,4 +114,4 @@ teardown() {

run bash -n "$REPO_ROOT/lib/ncdd-test.sh"
[ "$status" -eq 0 ]
}
}
Loading