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
2 changes: 2 additions & 0 deletions .docker/web/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
FROM nginx:alpine

RUN apk upgrade --no-cache

COPY nginx.conf /etc/nginx/nginx.conf
COPY nextcloud.conf /etc/nginx/nextcloud.conf
45 changes: 45 additions & 0 deletions .github/workflows/ncdd-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: NCDD CLI

on:
pull_request:
paths:
- 'bin/ncdd'
- 'tests/ncdd.bats'
- 'docs/ncdd.md'
- 'AGENTS.md'
- 'Makefile'
- '.github/workflows/ncdd-cli.yml'
push:
branches:
- main
paths:
- 'bin/ncdd'
- 'tests/ncdd.bats'
- 'docs/ncdd.md'
- 'AGENTS.md'
- 'Makefile'
- '.github/workflows/ncdd-cli.yml'

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Setup Bats
uses: bats-core/bats-action@77d6fb60505b4d0d1d73e48bd035b55074bbfb43 # 4.0.0
with:
support-install: false
assert-install: false
detik-install: false
file-install: false

- name: ShellCheck
run: shellcheck bin/ncdd

- name: Test
run: bats tests/ncdd.bats
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# NCDD agent contract

Use `bin/ncdd` for stack operations. Do not reproduce Docker Compose commands in agent instructions unless debugging NCDD itself.

Keep Git checkout and authentication outside the containers. App worktrees belong under `volumes/nextcloud/apps-extra/`.

Use `bin/ncdd doctor --json` for machine-readable environment diagnostics. See `docs/ncdd.md` for the command contract.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
COMPOSE ?= docker compose
GARAGES3_COMPOSE_FILE ?= docker-compose-garages3.yml

.PHONY: up-garages3 down-garages3 bootstrap-garages3 garage-status-garages3 start-garages3 wait-nextcloud-garages3 setup-garages3 test-hooks test-scan-images scan-images
.PHONY: up-garages3 down-garages3 bootstrap-garages3 garage-status-garages3 start-garages3 wait-nextcloud-garages3 setup-garages3 test-hooks test-scan-images test-ncdd scan-images

up-garages3:
$(COMPOSE) -f $(GARAGES3_COMPOSE_FILE) up -d garage
Expand Down Expand Up @@ -32,6 +32,9 @@ test-hooks:
test-scan-images:
bash tests/test-scan-images.sh

test-ncdd:
bats tests/ncdd.bats

scan-images:
@set -e; \
version="$$(sed -n 's/^NEXTCLOUD_VERSION=//p' .env.example | head -n 1)"; \
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ Languages avaliable: [pt-BR](docs/README_ptBR.md)
- [Logs](#logs)
- [Nextcloud Talk](#talk)

## NCDD command interface

For development automation, use the repository's `bin/ncdd` wrapper instead of reproducing Docker Compose details in CI, agents, or local instructions. It operates the existing `docker-compose.yml` and `docker-compose-postgres.yml`; it does not define a second stack.

```bash
bin/ncdd up
bin/ncdd doctor
bin/ncdd shell
bin/ncdd down
```

See [docs/ncdd.md](docs/ncdd.md) for the command contract and testing policy.

## Setup of docker

You need to have, on your server, the installed docker. The installation can be done with an official script, following the following steps:
Expand Down
187 changes: 187 additions & 0 deletions bin/ncdd
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#!/usr/bin/env bash
set -euo pipefail

NCDD_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
APP_SERVICE=${NCDD_APP_SERVICE:-app}
RUNTIME_USER=${NCDD_RUNTIME_USER:-www-data}

usage() {
cat <<'EOF'
Usage: ncdd <command> [options]

Commands:
up Start the existing NCDD stack
down Stop the existing NCDD stack
status Show stack status
env Show resolved NCDD environment
doctor [--json] Check Docker, Compose, app service, and Nextcloud
shell [--as USER] Open a shell in the app container
exec [--as USER] -- COMMAND...
Execute a command in the app container
help [ai] Show help or the compact agent contract
EOF
}

agent_help() {
cat <<'EOF'
NCDD agent contract
- Use bin/ncdd instead of calling docker compose directly.
- The CLI operates docker-compose.yml plus docker-compose-postgres.yml.
- Git checkout/authentication stays on the host or CI workspace.
- App worktrees belong under volumes/nextcloud/apps-extra/.
- Use --as runtime for commands that must run as the Nextcloud runtime user.
EOF
}

fail() {
printf 'ncdd: %s\n' "$*" >&2
exit 1
}

compose() {
docker compose \
--project-directory "$NCDD_ROOT" \
-f "$NCDD_ROOT/docker-compose.yml" \
-f "$NCDD_ROOT/docker-compose-postgres.yml" \
"$@"
}

ensure_network() {
local network=$1

if ! docker network inspect "$network" >/dev/null 2>&1; then
docker network create "$network" >/dev/null
fi
}

resolve_user() {
case "$1" in
runtime) printf '%s\n' "$RUNTIME_USER" ;;
root) printf 'root\n' ;;
*) printf '%s\n' "$1" ;;
esac
}

nextcloud_version() {
if [ -n "${NEXTCLOUD_VERSION:-}" ]; then
printf '%s\n' "$NEXTCLOUD_VERSION"
return
fi

local file
for file in "$NCDD_ROOT/.env" "$NCDD_ROOT/.env.example"; do
if [ -f "$file" ]; then
local value
value=$(sed -n 's/^NEXTCLOUD_VERSION=//p' "$file" | head -n 1)
if [ -n "$value" ]; then
printf '%s\n' "$value"
return
fi
fi
done

printf 'unset\n'
}

doctor() {
local json=false
if [ "${1:-}" = "--json" ]; then
json=true
shift
fi
[ "$#" -eq 0 ] || fail "doctor accepts only --json"

local docker_ok=false compose_ok=false app_running=false nextcloud_ready=false
command -v docker >/dev/null 2>&1 && docker_ok=true
if $docker_ok && docker compose version >/dev/null 2>&1; then
compose_ok=true
fi
if $compose_ok && compose ps --status running --services 2>/dev/null | grep -qx "$APP_SERVICE"; then
app_running=true
fi
if $app_running && compose exec -T --user "$RUNTIME_USER" "$APP_SERVICE" php occ status --output=json >/dev/null 2>&1; then
nextcloud_ready=true
fi

local ready=false
if $docker_ok && $compose_ok && $app_running && $nextcloud_ready; then
ready=true
fi

if $json; then
printf '{"ready":%s,"docker":%s,"compose":%s,"app_running":%s,"nextcloud_ready":%s,"nextcloud_version":"%s"}\n' \
"$ready" "$docker_ok" "$compose_ok" "$app_running" "$nextcloud_ready" "$(nextcloud_version)"
else
printf '%-20s %s\n' "Docker" "$docker_ok"
printf '%-20s %s\n' "Docker Compose" "$compose_ok"
printf '%-20s %s\n' "App running" "$app_running"
printf '%-20s %s\n' "Nextcloud ready" "$nextcloud_ready"
printf '%-20s %s\n' "Nextcloud version" "$(nextcloud_version)"
fi

$ready
}

command=${1:-help}
if [ "$#" -gt 0 ]; then
shift
fi

case "$command" in
help)
if [ "${1:-}" = "ai" ]; then
agent_help
else
usage
fi
;;
env)
printf 'NCDD_ROOT=%s\n' "$NCDD_ROOT"
printf 'NCDD_APP_SERVICE=%s\n' "$APP_SERVICE"
printf 'NCDD_RUNTIME_USER=%s\n' "$RUNTIME_USER"
printf 'NEXTCLOUD_VERSION=%s\n' "$(nextcloud_version)"
;;
up)
[ "$#" -eq 0 ] || fail "up does not accept arguments"
ensure_network reverse-proxy
ensure_network postgres
compose up -d redis postgres app web cron
;;
down)
compose down "$@"
;;
status)
compose ps "$@"
;;
shell)
user=root
if [ "${1:-}" = "--as" ]; then
user=$(resolve_user "${2:?missing user}")
shift 2
fi
[ "$#" -eq 0 ] || fail "unknown shell arguments: $*"
compose exec --user "$user" "$APP_SERVICE" bash
;;
exec)
user=root
if [ "${1:-}" = "--as" ]; then
user=$(resolve_user "${2:?missing user}")
shift 2
fi
if [ "${1:-}" = "--" ]; then
shift
fi
[ "$#" -gt 0 ] || fail "exec requires a command"
tty=()
if [ ! -t 0 ] || [ ! -t 1 ]; then
tty=(-T)
fi
compose exec "${tty[@]}" --user "$user" "$APP_SERVICE" "$@"
;;
doctor)
doctor "$@"
;;
*)
fail "unknown command: $command"
;;
esac
61 changes: 61 additions & 0 deletions docs/ncdd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# NCDD command interface

NCDD should expose a stable command surface without creating a second development stack.

## Architecture

`bin/ncdd` is a thin orchestration layer over the files that already define this repository:

- `docker-compose.yml`
- `docker-compose-postgres.yml`
- `.env` / `.env.example`

It must not duplicate the stack, own a second version source, or redefine image versions.

The Makefile remains focused on repository maintenance tasks. It only exposes `test-ncdd` as a convenience for running the CLI test suite; runtime behavior belongs to `bin/ncdd`.

## Commands

```bash
bin/ncdd up
bin/ncdd status
bin/ncdd doctor
bin/ncdd doctor --json
bin/ncdd shell
bin/ncdd exec --as runtime -- php occ status
bin/ncdd down
```

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

## 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.

Application worktrees should be placed under the existing Nextcloud tree:

```text
volumes/nextcloud/apps-extra/<app-id>
```

That keeps public and private branches identical from NCDD's point of view and avoids container-specific Git authentication.

## Version source

There is no NCDD version constant in the CLI. The Nextcloud image version is read from the existing `NEXTCLOUD_VERSION` environment variable, then `.env`, then `.env.example`.

A separate NCDD release/version mechanism should only be introduced if the project actually starts publishing the CLI independently.

## Testing

The CLI is Bash, so its behavior is covered with Bats rather than ad-hoc shell assertions. CI also runs ShellCheck.

```bash
make test-ncdd
```

The GitHub workflow pins the Bats setup action to an immutable commit SHA and pins the Bats version explicitly.

## Configuration policy

PR #59 intentionally does not introduce `.ncdd.yml`. Environment-specific project contracts may become useful for test-suite definitions later, but adding another configuration format before there is a concrete consumer requirement would duplicate information already present in Compose and `.env`.
Loading
Loading