-
-
Notifications
You must be signed in to change notification settings - Fork 763
Expand file tree
/
Copy pathcreate-configlet-sync-issues.yml
More file actions
176 lines (146 loc) · 6.71 KB
/
create-configlet-sync-issues.yml
File metadata and controls
176 lines (146 loc) · 6.71 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
name: Create Configlet Sync Issues
on:
workflow_call:
workflow_dispatch:
permissions:
issues: write
contents: read
jobs:
create-sync-issues:
runs-on: ubuntu-24.04
timeout-minutes: 15
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PARENT_ISSUE_TITLE: "🚨 configlet sync --test found unsynced tests"
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Fetch configlet
run: ./bin/fetch-configlet
- name: Run configlet sync --tests and capture output
id: sync
shell: bash {0}
run: |
raw_output="$(./bin/configlet sync --tests 2>&1)"
exit_code=$?
printf "exit_code=%d\n" "$exit_code" >> "$GITHUB_OUTPUT"
{
printf "output<<CONFIGLET_EOF\n"
printf "%s\n" "$raw_output"
printf "CONFIGLET_EOF\n"
} >> "$GITHUB_OUTPUT"
printf "configlet exit code: %d\n" "$exit_code"
printf "%s\n" "$raw_output"
- name: Parse exercises with missing tests
id: parse
if: steps.sync.outputs.exit_code != '0'
shell: bash
run: |
output='${{ steps.sync.outputs.output }}'
# Extract exercise slugs from lines like: [warn] dot-dsl: missing 19 test cases
mapfile -t exercises < <(printf "%s\n" "$output" | grep -oP '(?<=\[warn\] )[a-z][a-z0-9-]+(?=: missing \d+ test case)')
if [[ ${#exercises[@]} -eq 0 ]]; then
printf "No exercises with missing tests found in output.\n"
printf "exercises_json=[]\n" >> "$GITHUB_OUTPUT"
exit 0
fi
printf "Found %d exercise(s) with missing tests:\n" "${#exercises[@]}"
printf " - %s\n" "${exercises[@]}"
# Build JSON array of slugs
json="["
for i in "${!exercises[@]}"; do
[[ $i -gt 0 ]] && json+=","
json+="\"${exercises[$i]}\""
done
json+="]"
printf "exercises_json=%s\n" "$json" >> "$GITHUB_OUTPUT"
# Build per-exercise details: slug <TAB> test_name <TAB> uuid (one row per test)
{
printf "details<<DETAILS_EOF\n"
current_slug=""
while IFS= read -r line; do
if [[ "$line" =~ ^\[warn\]\ ([a-z][a-z0-9-]+):\ missing ]]; then
current_slug="${BASH_REMATCH[1]}"
elif [[ -n "$current_slug" && "$line" =~ ^[[:space:]]+-\ (.+)\ \(([a-f0-9-]+)\)$ ]]; then
printf "%s\t%s\t%s\n" "$current_slug" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
elif [[ "$line" =~ ^\[warn\] && ! "$line" =~ missing ]]; then
current_slug=""
fi
done <<< "$output"
printf "DETAILS_EOF\n"
} >> "$GITHUB_OUTPUT"
- name: Find parent tracking issue
id: find_parent
if: steps.sync.outputs.exit_code != '0' && steps.parse.outputs.exercises_json != '[]'
shell: bash
run: |
issue_data=$(gh issue list \
--repo "${{ github.repository }}" \
--search "is:issue is:open in:title \"${PARENT_ISSUE_TITLE}\"" \
--json number \
--jq '.[0].number // empty')
if [[ -z "$issue_data" ]]; then
printf "::warning::Parent issue not found. Run 'Run Configlet Sync' first.\n"
printf "parent_number=\n" >> "$GITHUB_OUTPUT"
else
printf "Found parent issue #%s\n" "$issue_data"
printf "parent_number=%s\n" "$issue_data" >> "$GITHUB_OUTPUT"
fi
- name: Create or update child issues per exercise
if: steps.sync.outputs.exit_code != '0' && steps.parse.outputs.exercises_json != '[]'
shell: bash
env:
EXERCISES_JSON: ${{ steps.parse.outputs.exercises_json }}
DETAILS: ${{ steps.parse.outputs.details }}
PARENT_NUMBER: ${{ steps.find_parent.outputs.parent_number }}
run: |
repo="${{ github.repository }}"
mapfile -t exercises < <(printf "%s\n" "$EXERCISES_JSON" | jq -r '.[]')
for slug in "${exercises[@]}"; do
child_title="[configlet] ${slug}: missing test cases"
# Collect missing tests for this exercise
missing_tests=""
while IFS=$'\t' read -r es_slug test_name uuid; do
[[ "$es_slug" == "$slug" ]] || continue
missing_tests+="- \`${uuid}\` ${test_name}"$'\n'
done <<< "$DETAILS"
parent_ref=""
[[ -n "$PARENT_NUMBER" ]] && parent_ref="Part of #${PARENT_NUMBER}."
# Write body to a temp file to avoid quoting / indentation issues
body_file=$(mktemp)
cat > "$body_file" << ISSUE_BODY_EOF
## Missing test cases for \`${slug}\`
${parent_ref}
The following test cases from [problem-specifications](https://github.com/exercism/problem-specifications/tree/main/exercises/${slug}) are not yet implemented in this track:
${missing_tests}
### How to help
For detailed instructions on how to fetch configlet and update the tests, please see the **"How to do this task"** section in the main tracking issue:
👉 **[Read the instructions here](${{ github.server_url }}/${{ github.repository }}/issues/${PARENT_NUMBER:-"none"})**
_This issue is managed automatically by the [Create Configlet Sync Issues](${{ github.server_url }}/${{ github.repository }}/actions/workflows/create-configlet-sync-issues.yml) workflow._
ISSUE_BODY_EOF
# Check for an existing open child issue
existing=$(gh issue list \
--repo "$repo" \
--search "is:issue is:open in:title \"${child_title}\"" \
--json number \
--jq '.[0].number // empty')
if [[ -z "$existing" ]]; then
printf "Creating child issue for: %s\n" "$slug"
issue_url=$(gh issue create \
--repo "$repo" \
--title "$child_title" \
--body-file "$body_file" \
--label "x:knowledge/elementary,x:module/practice-exercise")
new_number=$(basename "$issue_url")
printf "Created #%s for %s\n" "$new_number" "$slug"
else
printf "Updating existing child issue #%s for: %s\n" "$existing" "$slug"
gh issue edit "$existing" \
--repo "$repo" \
--body-file "$body_file"
fi
rm -f "$body_file"
done
- name: All tests synced — nothing to do
if: steps.sync.outputs.exit_code == '0'
run: printf "✅ All exercises are fully synced. No child issues needed.\n"