Files
redmine/docs/cli_runtime.md
T
2026-10-18 03:18:36 -04:00

4.0 KiB
Raw Blame History

Redmine CLI runtime

The live wrappers are deliberately short:

bin/rcontacts-live search acme
bin/rtickets-live search --where 'assigned_to IS NULL'
bin/rtl search --where 'assigned_to IS NULL'   # short live alias
bin/rtd search --where 'assigned_to IS NULL'   # explicit LAN/dev lane

--help works without credentials. The wrappers resolve configuration independently of the current working directory and pass ordinary arguments unchanged to redmine_contacts.py or redmine_tickets.py.

Diagnose configuration without API traffic

bin/rcontacts-live --doctor
bin/rtickets-live --show-config
bin/rtl --doctor-nmi

Diagnostics show effective paths and each setting’s source. Secrets are never printed. network_checked: false means readiness is local; it does not prove remote authentication.

Precedence and files

Highest priority wins:

  1. wrapper CLI options;
  2. exported environment;
  3. selected Redmine env file;
  4. ticket JSON/YAML --config values;
  5. defaults.

Select an env file with --env-file PATH or REDMINE_ENV_FILE. Otherwise the first existing file is used:

  • live: checkout .env, legacy bin/.env, ~/.redmine.live;
  • dev: checkout .env.dev, bin/.env.dev, ~/.redmine.dev.

Dev never falls back to the live file. An explicitly selected missing, empty, or malformed file is an error. Files use NAME=value and are parsed as data; shell commands are not evaluated.

REDMINE_API_KEY          required for API operations
REDMINE_BASE_URL         live default https://rm.ldrprep.com
REDMINE_PROJECT          default customer-service
REDMINE_BASE_CACHE       common mutable-data root
REDMINE_CONTACTS_CACHE   exact full-CRM snapshot JSON file
REDMINE_TICKETS_CACHE    exact ticket-cache directory
REDMINE_LOCK_TIMEOUT     writer wait, seconds; default 60
REDMINE_ENV_FILE         explicit env profile
REDMINE_API_KEY_FILE     file containing only the Redmine key

NMI bridge variables (NMI_CLI, NMI_ENV_FILE, NMI_MODE, endpoint/credential variables) pass through to PHP. rtl defaults NMI to production; rtd defaults it to dev. --doctor-nmi runs the actual PHP resolver offline.

Cache layout

REDMINE_BASE_CACHE chooses the common root, defaulting to checkout cache/ live and cache-dev/ dev.

  • Tickets normally use <root>/redmine_tickets/.
  • Other endpoint/project combinations get deterministic distinct ticket directories.
  • Fresh contacts setups use <root>/redmine_contacts/<host>_<project>.json.
  • If historical <root>/redmine_contacts is already a file for normal live use, the wrapper preserves and uses it. There is no automatic migration.
  • Tickets’ <ticket-cache>/contacts/ mirror is a different per-contact format, not the full contacts snapshot.

Exact --cache-dir DIR (tickets) and --cache FILE (contacts) win. Contacts rejects a cache directory because redmine_contacts.py expects one JSON file.

ticket-contact prints a shell-quoted full-CRM handoff that retains endpoint, project, env profile, API-key-file context, and cache file without putting a key in argv.

Concurrency and cron

Writers use POSIX advisory locks around read/modify/write transactions and unique same-directory temporary files followed by atomic replacement. A process’s death releases its kernel lock; the persistent .lock file is only an inode anchor. A later holder removes matching temporary residue left by a killed writer.

Contention is visible on stderr. After REDMINE_LOCK_TIMEOUT, the process exits nonzero rather than making a cron failure silent.

REDMINE_ENV_FILE=/etc/ldr/redmine-live.env /opt/redmine/bin/rtickets-live sync --remote-updated-since 6h --run-log --quiet

Completion and safety

source bin/redmine-runtime-completion.bash

This registers all four wrappers and includes the established contacts completion surface.

The wrappers do not weaken write safety: production ticket writes still require --allow-prod-writes; customer email still requires its long confirmation; NMI retains its independent mutation gates.