vinta-ai-workflows 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +830 -0
- package/LICENSE +21 -0
- package/README.md +547 -0
- package/package.json +27 -0
- package/schemas/README.md +84 -0
- package/schemas/mcp-preflight-cache.v1.schema.json +50 -0
- package/schemas/prs-context-comments.v1.schema.json +51 -0
- package/schemas/prs-context-frontmatter.v1.schema.json +77 -0
- package/schemas/sub-agent.v1.schema.json +105 -0
- package/schemas/vinta-ai-workflows-config.v1.schema.json +283 -0
- package/skills/vinta-analyze-codebase/SKILL.md +325 -0
- package/skills/vinta-bootstrap-ai-tools/SKILL.md +375 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/README.md +50 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/django/notes.md +52 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/medplum/notes.md +45 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/nextjs-app-router/notes.md +35 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/python-package/notes.md +31 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/typescript-monorepo/notes.md +32 -0
- package/skills/vinta-derive-skills/SKILL.md +200 -0
- package/skills/vinta-derive-skills/resources/amend-plan-template.md +355 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/SKILL.md +292 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/resources/one_off_script_base.py +602 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/resources/one_off_script_base.ts +624 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/create-qa-use-cases/SKILL.md +232 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/create-spec/SKILL.md +235 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/SKILL.md +78 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/scripts/open-pr.sh +357 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/SKILL.md +418 -0
- package/skills/vinta-derive-skills/resources/implement-plan-template.md +375 -0
- package/skills/vinta-derive-skills/resources/prs-context-template.md +91 -0
- package/skills/vinta-derive-skills/resources/systematic-debugging-mcp-tools.md +125 -0
- package/skills/vinta-derive-skills/resources/systematic-debugging-template.md +167 -0
- package/skills/vinta-derive-subagents/SKILL.md +192 -0
- package/skills/vinta-install-ai-tools-setup/SKILL.md +138 -0
- package/skills/vinta-install-ai-tools-setup/resources/setup-ai-tools.mjs +392 -0
- package/skills/vinta-migrate-plans-specs/SKILL.md +229 -0
- package/skills/vinta-sync-ai-tools/SKILL.md +184 -0
- package/skills/vinta-update-project-skills/SKILL.md +178 -0
- package/skills/vinta-write-agents-md/SKILL.md +192 -0
- package/vinta-ai-workflows.mjs +316 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# open-pr.sh — publish one .vinta-ai-workflows/prs-context/{feature}/{phase}.md file as a real PR
|
|
3
|
+
# + inline review comments via the project's PR CLI (`gh` for GitHub,
|
|
4
|
+
# `glab` for GitLab). Reads frontmatter + sections, opens the PR (or
|
|
5
|
+
# detects an existing one), posts each comment from the YAML list,
|
|
6
|
+
# rewrites the file's frontmatter to `status: published` + populated
|
|
7
|
+
# `pr_url`, and appends a publish log.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# open-pr.sh <path-to-prs-context-file> [--cli gh|glab] [--dry-run]
|
|
11
|
+
#
|
|
12
|
+
# Exit codes:
|
|
13
|
+
# 0 PR opened (or pre-existing); all comments posted.
|
|
14
|
+
# 1 PR opened; one or more comments failed to post.
|
|
15
|
+
# 2 Hard failure (file invalid, branch not pushed, CLI missing/unauthed,
|
|
16
|
+
# missing dependency).
|
|
17
|
+
#
|
|
18
|
+
# Dependencies:
|
|
19
|
+
# bash 4+, git, yq (Mike Farah's), jq, and one of: gh, glab.
|
|
20
|
+
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
# ── Output helpers ────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
die() { echo "open-pr: $*" >&2; exit 2; }
|
|
26
|
+
log() { echo "open-pr: $*"; }
|
|
27
|
+
|
|
28
|
+
require_cmd() {
|
|
29
|
+
command -v "$1" >/dev/null 2>&1 || die "missing dependency: $1"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# ── Args ──────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
FILE=""
|
|
35
|
+
CLI=""
|
|
36
|
+
DRY_RUN=0
|
|
37
|
+
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--cli) CLI="$2"; shift 2;;
|
|
41
|
+
--cli=*) CLI="${1#--cli=}"; shift;;
|
|
42
|
+
--dry-run|-n) DRY_RUN=1; shift;;
|
|
43
|
+
-h|--help)
|
|
44
|
+
echo "Usage: open-pr.sh <path> [--cli gh|glab] [--dry-run]"
|
|
45
|
+
exit 0
|
|
46
|
+
;;
|
|
47
|
+
--*) die "unknown arg: $1";;
|
|
48
|
+
*)
|
|
49
|
+
[[ -n "$FILE" ]] && die "unexpected positional arg: $1"
|
|
50
|
+
FILE="$1"; shift
|
|
51
|
+
;;
|
|
52
|
+
esac
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
[[ -n "$FILE" ]] || die "missing path to prs-context file"
|
|
56
|
+
[[ -f "$FILE" ]] || die "file not found: $FILE"
|
|
57
|
+
|
|
58
|
+
# ── Dep checks (after --help so it works without yq/jq installed) ────────
|
|
59
|
+
|
|
60
|
+
require_cmd git
|
|
61
|
+
require_cmd yq
|
|
62
|
+
require_cmd jq
|
|
63
|
+
|
|
64
|
+
# ── Parse the file ────────────────────────────────────────────────────────
|
|
65
|
+
# Format: --- frontmatter --- \n\n # Title \n ... \n # Description \n ... \n # Comments \n ```yaml ... ```
|
|
66
|
+
|
|
67
|
+
# Frontmatter: lines between the first two `---` markers.
|
|
68
|
+
FRONTMATTER=$(awk '
|
|
69
|
+
/^---$/ { count++; if (count == 2) exit; if (count == 1) next }
|
|
70
|
+
count == 1 { print }
|
|
71
|
+
' "$FILE")
|
|
72
|
+
|
|
73
|
+
# Body: everything after the second `---` line.
|
|
74
|
+
BODY=$(awk '
|
|
75
|
+
/^---$/ { count++; next }
|
|
76
|
+
count >= 2 { print }
|
|
77
|
+
' "$FILE")
|
|
78
|
+
|
|
79
|
+
[[ -n "$FRONTMATTER" ]] || die "$FILE: missing YAML frontmatter (--- ... ---)"
|
|
80
|
+
|
|
81
|
+
# Extract typed fields from frontmatter via yq.
|
|
82
|
+
get_meta() { echo "$FRONTMATTER" | yq -r ".${1} // \"\""; }
|
|
83
|
+
|
|
84
|
+
BRANCH=$(get_meta branch)
|
|
85
|
+
BASE=$(get_meta base)
|
|
86
|
+
STATUS=$(get_meta status)
|
|
87
|
+
PR_URL=$(get_meta pr_url)
|
|
88
|
+
PLAN_ID=$(get_meta plan_id)
|
|
89
|
+
PHASE_ID=$(get_meta phase_id)
|
|
90
|
+
|
|
91
|
+
[[ -n "$BRANCH" ]] || die "$FILE: frontmatter missing required 'branch'"
|
|
92
|
+
[[ -n "$BASE" ]] || die "$FILE: frontmatter missing required 'base'"
|
|
93
|
+
|
|
94
|
+
# Already published?
|
|
95
|
+
if [[ "$STATUS" == "published" && -n "$PR_URL" && "$PR_URL" != "null" ]]; then
|
|
96
|
+
log "already published: $PR_URL"
|
|
97
|
+
exit 0
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Body sections — split on `^# ` H1 headings.
|
|
101
|
+
extract_section() {
|
|
102
|
+
local heading="$1"
|
|
103
|
+
echo "$BODY" | awk -v h="^# +${heading}\$" '
|
|
104
|
+
$0 ~ h { in_sec = 1; next }
|
|
105
|
+
/^# / && in_sec { in_sec = 0 }
|
|
106
|
+
in_sec { print }
|
|
107
|
+
' | sed -e ':a;/./,$!d;/^$/{$d;ba;}' # trim trailing blank lines
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
TITLE=$(extract_section "Title" | sed -e '/./,$!d')
|
|
111
|
+
DESCRIPTION=$(extract_section "Description")
|
|
112
|
+
COMMENTS_RAW=$(extract_section "Comments")
|
|
113
|
+
|
|
114
|
+
[[ -n "$TITLE" ]] || die "$FILE: # Title section is empty"
|
|
115
|
+
[[ -n "$DESCRIPTION" ]] || die "$FILE: # Description section is empty"
|
|
116
|
+
|
|
117
|
+
# Comments are inside ```yaml ... ``` fence within the # Comments section.
|
|
118
|
+
COMMENTS_YAML=$(echo "$COMMENTS_RAW" | awk '
|
|
119
|
+
/^```ya?ml$/ { in_fence = 1; next }
|
|
120
|
+
/^```$/ && in_fence { in_fence = 0; next }
|
|
121
|
+
in_fence { print }
|
|
122
|
+
')
|
|
123
|
+
|
|
124
|
+
# Convert comments YAML to JSON for jq iteration. Empty list when no fence.
|
|
125
|
+
if [[ -z "$COMMENTS_YAML" ]]; then
|
|
126
|
+
COMMENTS_JSON='[]'
|
|
127
|
+
else
|
|
128
|
+
COMMENTS_JSON=$(echo "$COMMENTS_YAML" | yq -o=json '.' 2>/dev/null || echo '[]')
|
|
129
|
+
[[ "$COMMENTS_JSON" == "null" ]] && COMMENTS_JSON='[]'
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
COMMENT_COUNT=$(echo "$COMMENTS_JSON" | jq 'length')
|
|
133
|
+
|
|
134
|
+
# ── Detect CLI + verify ──────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
if [[ -z "$CLI" ]]; then
|
|
137
|
+
if command -v gh >/dev/null 2>&1; then CLI=gh
|
|
138
|
+
elif command -v glab >/dev/null 2>&1; then CLI=glab
|
|
139
|
+
else die "no PR CLI found in PATH (gh or glab). install one or pass --cli"
|
|
140
|
+
fi
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
case "$CLI" in
|
|
144
|
+
gh|glab) ;;
|
|
145
|
+
*) die "unsupported --cli: $CLI";;
|
|
146
|
+
esac
|
|
147
|
+
|
|
148
|
+
require_cmd "$CLI"
|
|
149
|
+
log "using $CLI"
|
|
150
|
+
|
|
151
|
+
if [[ $DRY_RUN -eq 0 ]]; then
|
|
152
|
+
# Auth check.
|
|
153
|
+
"$CLI" auth status >/dev/null 2>&1 || die "$CLI not authenticated. run: $CLI auth login"
|
|
154
|
+
|
|
155
|
+
# Branch pushed?
|
|
156
|
+
git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1 \
|
|
157
|
+
|| die "branch not pushed: origin/$BRANCH. push it first."
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# ── Open PR (or detect existing) ─────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
PR_URL_NEW=""
|
|
163
|
+
PR_NUMBER=""
|
|
164
|
+
PR_IS_NEW=0
|
|
165
|
+
|
|
166
|
+
open_pr_gh() {
|
|
167
|
+
# Detect existing PR for branch.
|
|
168
|
+
local existing
|
|
169
|
+
if existing=$(gh pr view "$BRANCH" --json url,number 2>/dev/null); then
|
|
170
|
+
PR_URL_NEW=$(echo "$existing" | jq -r '.url')
|
|
171
|
+
PR_NUMBER=$(echo "$existing" | jq -r '.number')
|
|
172
|
+
PR_IS_NEW=0
|
|
173
|
+
return 0
|
|
174
|
+
fi
|
|
175
|
+
local out
|
|
176
|
+
out=$(gh pr create \
|
|
177
|
+
--base "$BASE" \
|
|
178
|
+
--head "$BRANCH" \
|
|
179
|
+
--title "$TITLE" \
|
|
180
|
+
--body "$DESCRIPTION" 2>&1) \
|
|
181
|
+
|| die "gh pr create failed: $out"
|
|
182
|
+
PR_URL_NEW=$(echo "$out" | tail -n1 | tr -d '[:space:]')
|
|
183
|
+
PR_NUMBER=$(echo "$PR_URL_NEW" | grep -oE '/pull/[0-9]+' | grep -oE '[0-9]+')
|
|
184
|
+
PR_IS_NEW=1
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
open_pr_glab() {
|
|
188
|
+
local existing
|
|
189
|
+
if existing=$(glab mr view "$BRANCH" -F json 2>/dev/null); then
|
|
190
|
+
PR_URL_NEW=$(echo "$existing" | jq -r '.web_url')
|
|
191
|
+
PR_NUMBER=$(echo "$existing" | jq -r '.iid')
|
|
192
|
+
PR_IS_NEW=0
|
|
193
|
+
return 0
|
|
194
|
+
fi
|
|
195
|
+
local out
|
|
196
|
+
out=$(glab mr create \
|
|
197
|
+
--target-branch "$BASE" \
|
|
198
|
+
--source-branch "$BRANCH" \
|
|
199
|
+
--title "$TITLE" \
|
|
200
|
+
--description "$DESCRIPTION" \
|
|
201
|
+
--yes 2>&1) \
|
|
202
|
+
|| die "glab mr create failed: $out"
|
|
203
|
+
PR_URL_NEW=$(echo "$out" | grep -oE 'https?://[^[:space:]]+' | head -n1)
|
|
204
|
+
PR_NUMBER=$(echo "$PR_URL_NEW" | grep -oE '/[0-9]+$' | tr -d '/')
|
|
205
|
+
PR_IS_NEW=1
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if [[ $DRY_RUN -eq 1 ]]; then
|
|
209
|
+
PR_URL_NEW="<dry-run>"
|
|
210
|
+
PR_NUMBER="0"
|
|
211
|
+
PR_IS_NEW=1
|
|
212
|
+
else
|
|
213
|
+
case "$CLI" in
|
|
214
|
+
gh) open_pr_gh ;;
|
|
215
|
+
glab) open_pr_glab ;;
|
|
216
|
+
esac
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
if [[ $PR_IS_NEW -eq 1 ]]; then
|
|
220
|
+
log "PR opened → $PR_URL_NEW"
|
|
221
|
+
else
|
|
222
|
+
log "PR already existed → $PR_URL_NEW"
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# ── Post inline comments ─────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
PUBLISH_LOG=()
|
|
228
|
+
NOW() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
229
|
+
|
|
230
|
+
if [[ $PR_IS_NEW -eq 1 ]]; then
|
|
231
|
+
PUBLISH_LOG+=("$(NOW) — opened: $PR_URL_NEW")
|
|
232
|
+
else
|
|
233
|
+
PUBLISH_LOG+=("$(NOW) — reused existing PR: $PR_URL_NEW")
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
FAILURES=0
|
|
237
|
+
|
|
238
|
+
post_comment_gh() {
|
|
239
|
+
local file="$1" start="$2" end="$3" side="$4" body="$5"
|
|
240
|
+
local repo commit
|
|
241
|
+
repo=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
242
|
+
commit=$(git rev-parse "origin/$BRANCH")
|
|
243
|
+
local args=(
|
|
244
|
+
api --method POST
|
|
245
|
+
-H "Accept: application/vnd.github+json"
|
|
246
|
+
"/repos/$repo/pulls/$PR_NUMBER/comments"
|
|
247
|
+
-f "body=$body"
|
|
248
|
+
-f "commit_id=$commit"
|
|
249
|
+
-f "path=$file"
|
|
250
|
+
-F "line=${end:-$start}"
|
|
251
|
+
-f "side=${side:-RIGHT}"
|
|
252
|
+
)
|
|
253
|
+
if [[ -n "$end" && "$end" != "$start" && "$end" != "null" ]]; then
|
|
254
|
+
args+=( -F "start_line=$start" -f "start_side=${side:-RIGHT}" )
|
|
255
|
+
fi
|
|
256
|
+
gh "${args[@]}" >/dev/null 2>&1
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
post_comment_glab() {
|
|
260
|
+
local file="$1" start="$2" end="$3" _side="$4" body="$5"
|
|
261
|
+
local refs
|
|
262
|
+
refs=$(glab mr view "$PR_NUMBER" -F json | jq -r '.diff_refs')
|
|
263
|
+
local base_sha head_sha start_sha
|
|
264
|
+
base_sha=$(echo "$refs" | jq -r '.base_sha')
|
|
265
|
+
head_sha=$(echo "$refs" | jq -r '.head_sha')
|
|
266
|
+
start_sha=$(echo "$refs" | jq -r '.start_sha')
|
|
267
|
+
glab api --method POST \
|
|
268
|
+
"projects/:id/merge_requests/$PR_NUMBER/discussions" \
|
|
269
|
+
-f "body=$body" \
|
|
270
|
+
-f "position[base_sha]=$base_sha" \
|
|
271
|
+
-f "position[head_sha]=$head_sha" \
|
|
272
|
+
-f "position[start_sha]=$start_sha" \
|
|
273
|
+
-f "position[position_type]=text" \
|
|
274
|
+
-f "position[new_path]=$file" \
|
|
275
|
+
-f "position[new_line]=${end:-$start}" \
|
|
276
|
+
>/dev/null 2>&1
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if [[ "$COMMENT_COUNT" -eq 0 ]]; then
|
|
280
|
+
log "no inline comments to post"
|
|
281
|
+
elif [[ $DRY_RUN -eq 1 ]]; then
|
|
282
|
+
log "would post $COMMENT_COUNT comment(s) (dry-run)"
|
|
283
|
+
else
|
|
284
|
+
for ((i = 0; i < COMMENT_COUNT; i++)); do
|
|
285
|
+
file=$(echo "$COMMENTS_JSON" | jq -r ".[$i].file")
|
|
286
|
+
start=$(echo "$COMMENTS_JSON" | jq -r ".[$i].start_line")
|
|
287
|
+
end=$(echo "$COMMENTS_JSON" | jq -r ".[$i].end_line // \"\"")
|
|
288
|
+
side=$(echo "$COMMENTS_JSON" | jq -r ".[$i].side // \"RIGHT\"")
|
|
289
|
+
body=$(echo "$COMMENTS_JSON" | jq -r ".[$i].body")
|
|
290
|
+
label="$file:$start"
|
|
291
|
+
[[ -n "$end" && "$end" != "null" && "$end" != "$start" ]] && label="$label-$end"
|
|
292
|
+
|
|
293
|
+
if [[ "$CLI" == "gh" ]]; then
|
|
294
|
+
if post_comment_gh "$file" "$start" "$end" "$side" "$body"; then
|
|
295
|
+
echo " comment $((i + 1))/$COMMENT_COUNT posted ($label)"
|
|
296
|
+
PUBLISH_LOG+=("$(NOW) — comment $((i + 1))/$COMMENT_COUNT posted ($label)")
|
|
297
|
+
else
|
|
298
|
+
FAILURES=$((FAILURES + 1))
|
|
299
|
+
echo " comment $((i + 1))/$COMMENT_COUNT FAILED ($label)" >&2
|
|
300
|
+
PUBLISH_LOG+=("$(NOW) — comment $((i + 1))/$COMMENT_COUNT FAILED ($label)")
|
|
301
|
+
fi
|
|
302
|
+
else
|
|
303
|
+
if post_comment_glab "$file" "$start" "$end" "$side" "$body"; then
|
|
304
|
+
echo " comment $((i + 1))/$COMMENT_COUNT posted ($label)"
|
|
305
|
+
PUBLISH_LOG+=("$(NOW) — comment $((i + 1))/$COMMENT_COUNT posted ($label)")
|
|
306
|
+
else
|
|
307
|
+
FAILURES=$((FAILURES + 1))
|
|
308
|
+
echo " comment $((i + 1))/$COMMENT_COUNT FAILED ($label)" >&2
|
|
309
|
+
PUBLISH_LOG+=("$(NOW) — comment $((i + 1))/$COMMENT_COUNT FAILED ($label)")
|
|
310
|
+
fi
|
|
311
|
+
fi
|
|
312
|
+
done
|
|
313
|
+
fi
|
|
314
|
+
|
|
315
|
+
# ── Rewrite frontmatter + append publish log ─────────────────────────────
|
|
316
|
+
|
|
317
|
+
if [[ $DRY_RUN -eq 0 ]]; then
|
|
318
|
+
# Update frontmatter status + pr_url.
|
|
319
|
+
NEW_FM=$(echo "$FRONTMATTER" | yq -y \
|
|
320
|
+
".status = \"published\" | .pr_url = \"$PR_URL_NEW\"" 2>/dev/null \
|
|
321
|
+
|| echo "$FRONTMATTER" | yq \
|
|
322
|
+
".status = \"published\" | .pr_url = \"$PR_URL_NEW\"")
|
|
323
|
+
|
|
324
|
+
# Compose publish log block.
|
|
325
|
+
LOG_BLOCK=$'\n## Publish log\n\n'
|
|
326
|
+
for entry in "${PUBLISH_LOG[@]}"; do
|
|
327
|
+
LOG_BLOCK+="- $entry"$'\n'
|
|
328
|
+
done
|
|
329
|
+
|
|
330
|
+
# If body already has a publish log, append entries to it; else add new section.
|
|
331
|
+
if echo "$BODY" | grep -q '^## Publish log'; then
|
|
332
|
+
NEW_BODY=$(echo "$BODY" | awk -v entries="$(printf '%s\n' "${PUBLISH_LOG[@]}" | sed 's/^/- /')" '
|
|
333
|
+
/^## Publish log/ { in_log = 1; print; next }
|
|
334
|
+
/^## / && in_log { in_log = 0; print entries; print; next }
|
|
335
|
+
{ print }
|
|
336
|
+
END { if (in_log) print entries }
|
|
337
|
+
')
|
|
338
|
+
else
|
|
339
|
+
NEW_BODY="${BODY%$'\n'}"$'\n'"${LOG_BLOCK}"
|
|
340
|
+
fi
|
|
341
|
+
|
|
342
|
+
{
|
|
343
|
+
echo '---'
|
|
344
|
+
echo "$NEW_FM"
|
|
345
|
+
echo '---'
|
|
346
|
+
echo "$NEW_BODY"
|
|
347
|
+
} > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
|
|
348
|
+
|
|
349
|
+
log "updated $FILE (status=published, pr_url=$PR_URL_NEW)"
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
if [[ $FAILURES -gt 0 ]]; then
|
|
353
|
+
log "completed with $FAILURES comment failure(s)"
|
|
354
|
+
exit 1
|
|
355
|
+
fi
|
|
356
|
+
|
|
357
|
+
exit 0
|