-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnfrs-cli.sh
More file actions
executable file
·187 lines (162 loc) · 5.48 KB
/
nfrs-cli.sh
File metadata and controls
executable file
·187 lines (162 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env bash
set -euo pipefail
# Simple helper for using the NFRs toolkit against a project repo.
# When embedded, this script may live in <repo-root>/nfrs-toolkit/nfrs-cli.sh.
# Directory where this script resides (the toolkit root when embedded).
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Toolkit root is where this script lives in the extracted repo.
TOOLKIT_ROOT="${SCRIPT_DIR}"
# For backward compatibility, REPO_ROOT refers to the parent of the toolkit
# when embedded inside another repo. In the standalone toolkit repo this will
# just behave like a generic parent directory and is mainly used as a fallback.
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
# Prefer python if available, otherwise fall back to python3
if command -v python >/dev/null 2>&1; then
PYTHON_CMD="python"
elif command -v python3 >/dev/null 2>&1; then
PYTHON_CMD="python3"
else
echo "[nfrs-cli] Error: neither 'python' nor 'python3' found on PATH" >&2
exit 1
fi
usage() {
cat <<EOF
Usage: nfrs-cli.sh <command> [options]
Commands:
init --target PATH Initialise PATH with baseline NFRs
serve [--nfr-root PATH] Run NFR maintenance UI/API against PATH (default: this repo's requirements/nfrs)
generate [--nfr-root PATH] Generate markdown/pages for the NFRs at PATH
publish-confluence [--nfr-root PATH]
Publish generated markdown for PATH to Confluence (env must provide secrets)
Examples:
./nfrs-toolkit/nfrs-cli.sh serve
./nfrs-toolkit/nfrs-cli.sh serve --nfr-root /path/to/other/repo/requirements/nfrs
./nfrs-toolkit/nfrs-cli.sh generate
./nfrs-toolkit/nfrs-cli.sh publish-confluence
EOF
}
init() {
local target=""
while [[ $# -gt 0 ]]; do
case "$1" in
--target)
shift
target="${1:-}"
shift || true
;;
-h|--help)
echo "Usage: nfrs-cli.sh init --target /path/to/repo/requirements/nfrs" >&2
exit 0
;;
*)
echo "[nfrs-cli] Unknown arg for init: $1" >&2
exit 1
;;
esac
done
if [[ -z "$target" ]]; then
echo "Usage: nfrs-cli.sh init --target /path/to/repo/requirements/nfrs" >&2
exit 1
fi
# Resolve target to absolute path
if [[ "${target}" != /* ]]; then
target="$(cd "${PWD}" && mkdir -p "${target}" && cd "${target}" && pwd)"
fi
echo "[nfrs-cli] Initialising NFRs at ${target}"
# Ensure target directory exists
mkdir -p "${target}"
# Refuse to overwrite an existing non-empty directory to avoid accidental data loss
if [[ -n "$(ls -A "${target}")" ]]; then
echo "[nfrs-cli] Refusing to initialise non-empty directory: ${target}" >&2
echo "[nfrs-cli] Please choose an empty target or move existing NFRs aside first." >&2
exit 1
fi
# Baseline NFRs live under the same directory as this script
local script_dir baseline_root
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
baseline_root="${script_dir}"
# Baseline lives under ${baseline_root}/nfrs
rsync -a "${baseline_root}/nfrs/" "${target}/"
}
if [[ $# -lt 1 ]]; then
usage
exit 1
fi
COMMAND="$1"; shift || true
# init does not use NFR_ROOT; pass its arguments through untouched.
if [[ "${COMMAND}" == "init" ]]; then
init "$@"
exit 0
fi
# Default NFR root:
# - honour existing NFR_BASE_PATH if set (e.g. in Docker/compose)
# - otherwise, use this repo's requirements/nfrs directory.
if [[ -n "${NFR_BASE_PATH:-}" ]]; then
NFR_ROOT="${NFR_BASE_PATH}"
else
NFR_ROOT="${TOOLKIT_ROOT}/requirements/nfrs"
fi
while [[ $# -gt 0 ]]; do
case "$1" in
--nfr-root)
shift
NFR_ROOT="${1:-}"
shift || true
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage
exit 1
;;
esac
done
# Resolve NFR_ROOT to an absolute path. If a relative path was provided,
# interpret it relative to the repository root so that consumers (Node/Python)
# see a stable, absolute NFR_BASE_PATH regardless of the current working
# directory when commands run.
if [[ "${NFR_ROOT}" != /* ]]; then
NFR_ROOT="$(cd "${REPO_ROOT}" && cd "${NFR_ROOT}" && pwd)"
fi
export NFR_BASE_PATH="${NFR_ROOT}"
case "${COMMAND}" in
serve)
echo "[nfrs-cli] Serving NFR UI for NFR_BASE_PATH=${NFR_BASE_PATH}" >&2
cd "${TOOLKIT_ROOT}/src/nfrs-maintenance"
npm install
npm run dev
;;
generate)
echo "[nfrs-cli] Generating NFR pages for NFR_BASE_PATH=${NFR_BASE_PATH}" >&2
# Project root is derived from NFR_BASE_PATH, which usually points at
# <project-root>/requirements/nfrs. Walk up two levels to get the repo.
project_root="${REPO_ROOT}"
if [[ -n "${NFR_BASE_PATH:-}" ]]; then
project_root="$(cd "${NFR_BASE_PATH}/../.." && pwd)"
fi
cd "${project_root}"
"${PYTHON_CMD}" "${TOOLKIT_ROOT}/scripts/nfr/build_all_nfr_pages.py"
;;
publish-confluence)
echo "[nfrs-cli] Publishing NFR pages for NFR_BASE_PATH=${NFR_BASE_PATH}" >&2
# As with generate, publish works relative to the project repo root.
project_root="${REPO_ROOT}"
if [[ -n "${NFR_BASE_PATH:-}" ]]; then
project_root="$(cd "${NFR_BASE_PATH}/../.." && pwd)"
fi
cd "${project_root}"
# Expect caller to have already set CONFLUENCE_*/JIRA_* env vars
"${PYTHON_CMD}" scripts/confluence/publish_markdown.py \
--jira-macro --allow-create-if-missing \
docs/nfrs/nfr-by-domain.md docs/nfrs/nfr-by-domain/*.md \
docs/nfrs/nfr-by-service.md docs/nfrs/nfr-by-service/*/*.md
;;
*)
echo "Unknown command: ${COMMAND}" >&2
usage
exit 1
;;
esac