-
Notifications
You must be signed in to change notification settings - Fork 0
/
adrctl
executable file
·171 lines (136 loc) · 4.77 KB
/
adrctl
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
#!/bin/sh -eu
# adrctl - CLI helper for markdown ADR (MADR) documents
# This was meant to help maintain and organize ADR docs inside a local folder
# (ideally inside a git repo). adrctl should be simple, minimal and intuitive
# to use.
#
# Based on MADR spec at https://adr.github.io/madr (https://github.com/adr/madr)
# ------------------------------------------------------------------------------
# Config vars
# ------------------------------------------------------------------------------
# Set to anything to enable debug mode
ADRCTL_DEBUG=${ADRCTL_DEBUG:-}
# Project folder (e.g. generally your project git root folder)
ADRCTL_ROOT=${ADRCTL_ROOT:-"$(pwd)"}
# Path inside the project where ADR docs are stored (standard is 'docs/decisions')
ADRCTL_ADR_FOLDER=${ADRCTL_ADR_FOLDER:-"docs/decisions"}
# ------------------------------------------------------------------------------
# Internal constants
# ------------------------------------------------------------------------------
__ADR_FOLDER_PATH="$ADRCTL_ROOT/$ADRCTL_ADR_FOLDER"
__ADR_TEMPLATE_SHORT="# {{TITLE}}
## Context and Problem Statement
{Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story.
You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.}
## Considered Options
* {title of option 1}
* {title of option 2}
* {title of option 3}
* … <!-- numbers of options can vary -->
## Decision Outcome
Chosen option: \"{title of option 1}\", because
{justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | … | comes out best (see below)}.
"
# ------------------------------------------------------------------------------
# Logging utils
# ------------------------------------------------------------------------------
log() {
printf '%s\n' "$1"
}
log_debug() {
[ -z "$ADRCTL_DEBUG" ] && return
printf '%s\n' "$1"
}
log_green() {
printf '\033[32m%s\033[39m\n' "$1"
}
log_red() {
printf '\033[31m%s\033[39m\n' "$1"
}
# ------------------------------------------------------------------------------
# Helper functions
# ------------------------------------------------------------------------------
show_help() {
cat <<EOF
adrctl - ADR docs helper
Available commands:
new <title> Create new ADR doc with title
list List all ADRs
help|--help|-h Show this help message and exit with error
EOF
}
__get_all_adrs() {
echo "$__ADR_FOLDER_PATH"/*.md | grep -E "[0-9]{4}-(.*?)"
}
__calculate_next_adr_id() {
last=0
# TODO: better implementation without loop
for adr_f in $(__get_all_adrs); do
id="$(basename "$adr_f" | cut -d- -f1)"
# note: using float to prevent octal prefix...
# see https://stackoverflow.com/questions/8078167/printf-in-bash-09-and-08-are-invalid-numbers-07-and-06-are-fine
trimmed_id="$(printf '%f' "$id" | cut -d. -f1)"
if [ "$trimmed_id" -ge "$last" ]; then
last="$trimmed_id"
fi
done
echo "$(( last + 1 ))"
}
# Create new ADR file with title
adrctl_new() {
mkdir -p "$__ADR_FOLDER_PATH"
doc_name="$1"
adr_id="$(__calculate_next_adr_id)"
adr_padded_id="$(printf '%4s' "$adr_id" | sed 's# #0#g')"
file_title_lowercase="$(echo "$doc_name" | tr '[:upper:]' '[:lower:]')"
file_title_dashed="$(echo "$file_title_lowercase" | sed 's# #-#g')"
parsed_template="$(echo "$__ADR_TEMPLATE_SHORT" | sed "s#{{TITLE}}#$doc_name#")"
adr_file_name="$__ADR_FOLDER_PATH/$adr_padded_id-$file_title_dashed.md"
adr_file_name_pretty="$(basename "$adr_file_name")"
log "-- Creating new ADR: $adr_file_name_pretty"
if [ -f "$adr_file_name" ]; then
log_red "ERROR: ADR named '$adr_file_name_pretty' already exists."
return 1
fi
echo "$parsed_template" > "$adr_file_name"
}
# List all ADR documents found for the project
adrctl_list() {
if [ ! -d "$__ADR_FOLDER_PATH" ]; then
log_red 'ERROR: no ADR decisions folder found'
return 1
fi
for file in $(__get_all_adrs); do
[ -e "$file" ] || break # no files found
basename "$file"
done
}
# ------------------------------------------------------------------------------
# Main cli logic
# ------------------------------------------------------------------------------
cmd="${1:-}"
if [ -z "$cmd" ]; then
show_help
exit 1
fi
shift
case "$cmd" in
new)
doc_name="${*}"
adrctl_new "$doc_name"
exit $?
;;
list)
adrctl_list
exit $?
;;
help|--help|-h)
show_help
exit 1
;;
*)
log_red "ERROR: invalid command: $cmd"
show_help
exit 1
;;
esac