Skip to content

Commit af4a3a9

Browse files
Debugging
1 parent 123a435 commit af4a3a9

1 file changed

Lines changed: 66 additions & 100 deletions

File tree

.github/workflows/cleanup-workflows.yml

Lines changed: 66 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -55,99 +55,77 @@ jobs:
5555
echo "EOF"
5656
} >> "$GITHUB_OUTPUT"
5757
58-
- name: Workflows on github
59-
id: github
58+
- name: Filter for deleted workflows
59+
id: deleted
6060
env:
6161
GH_TOKEN: ${{ github.token }}
6262
run: |
63-
# Note that we filter by `.github` path prefix to ensure we only get locally defined workflows.
64-
#
65-
# Examples of non-local workflows are `dependabot` and `copilot` which have paths:
66-
# - dynamic/dependabot/dependabot-updates
67-
# - dynamic/copilot-pull-request-reviewer/copilot-pull-request-reviewer
68-
WORKFLOWS=$(gh workflow list \
69-
--all \
70-
--json path \
71-
--jq '.[] | select(.path | startswith(".github")) | .path' \
72-
)
73-
printf "%s\n" $WORKFLOWS
74-
{
75-
echo "workflows<<EOF"
76-
echo "$WORKFLOWS"
77-
echo "EOF"
78-
} >> "$GITHUB_OUTPUT"
63+
set -euo pipefail
7964
80-
- name: Filter for deleted workflows
81-
id: deleted
82-
run: |
83-
# Union of `main` and `next` workflows.
84-
EXISTING_FILES=$( \
85-
printf "%s\n%s\n" \
65+
# Union of `main` and `next` workflows as a JSON array of strings (paths)
66+
EXISTING=$(printf "%s\n%s\n" \
8667
"${{ steps.main.outputs.workflows }}" \
8768
"${{ steps.next.outputs.workflows }}" \
8869
)
89-
EXISTING_FILES=$(echo "$EXISTING_FILES" | sort -u)
90-
printf "%s\n" $EXISTING_FILES
91-
92-
# Find deleted workflows as the items in `WORKFLOWS` but not in the union of main and next.
93-
# This assumes that _all_ items in main and next are present in `WORKFLOWS`.
94-
DELETED_FILES=$( \
95-
printf "%s\n%s\n" \
96-
"$EXISTING_FILES" \
97-
"${{ steps.github.outputs.workflows }}" \
70+
EXISTING_JSON=$(echo "$EXISTING" | sort -u | jq -R . | jq -s .)
71+
72+
echo "Existing workflows:"
73+
echo "$EXISTING_JSON"
74+
75+
# Get workflows currently on GitHub as JSON array of objects
76+
GITHUB=$(gh workflow list --all --json path,name,id)
77+
GITHUB=$(echo "$GITHUB" | jq '[.[] | select(.path | startswith(".github/"))]')
78+
79+
echo "Workflows on GitHub:"
80+
echo "$GITHUB"
81+
82+
# Find deleted workflows: present on GitHub but not in main/next
83+
DELETED=$(jq -c \
84+
--argjson github "$GITHUB" \
85+
--argjson existing "$EXISTING" '
86+
$github | map(select(.path as $p | $existing | index($p) | not))
87+
'
9888
)
99-
DELETED_FILES=$(echo "$DELETED_FILES" | sort | uniq -u)
100-
printf "%s\n" $DELETED_FILES
89+
90+
echo "Deleted workflows:"
91+
echo "$DELETED"
92+
93+
# Output to GitHub Actions
10194
{
10295
echo "workflows<<EOF"
103-
echo "$DELETED_FILES"
96+
echo "$DELETED"
10497
echo "EOF"
10598
} >> "$GITHUB_OUTPUT"
10699
107100
- name: Delete runs from deleted workflows
108101
env:
109102
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110103
MODE: ${{ inputs.mode }}
111-
DELETED_WORKFLOWS: ${{ steps.deleted.outputs.workflows }}
104+
WORKFLOWS: ${{ steps.deleted.outputs.workflows }}
112105
OWNER: ${{ github.repository_owner }}
113106
REPO: ${{ github.repository }}
114107
run: |
115108
set -euo pipefail
116109
110+
if [[ -z "$WORKFLOWS" ]]; then
111+
echo "No workflows to delete."
112+
exit 0
113+
fi
114+
117115
TOTAL_AFFECTED=0
118116
SUMMARY=()
119-
120-
# Read workflows into an array for indexing
121-
mapfile -t WORKFLOWS_ARRAY <<< "$DELETED_WORKFLOWS"
122-
TOTAL_WORKFLOWS=${#WORKFLOWS_ARRAY[@]}
123-
124-
# Convert workflow paths to workflow names
125-
WORKFLOW_NAMES_ARRAY=()
126-
for wf_path in "${WORKFLOWS_ARRAY[@]}"; do
127-
# Extract 'name' from YAML, fallback to filename
128-
name=$(yq -r '.name // ""' "$wf_path" 2>/dev/null || true)
129-
if [ -z "$name" ]; then
130-
name=$(basename "$wf_path")
131-
fi
132-
WORKFLOW_NAMES_ARRAY+=("$name")
133-
done
134-
135-
# Determine max workflow name length for alignment
136-
MAX_WF_LENGTH=0
137-
for wf in "${WORKFLOW_NAMES_ARRAY[@]}"; do
138-
len=${#wf}
139-
(( len > MAX_WF_LENGTH )) && MAX_WF_LENGTH=$len
140-
done
141-
(( MAX_WF_LENGTH < 30 )) && MAX_WF_LENGTH=30 # minimum width
117+
CURRENT_INDEX=0
142118
143119
# Column widths
144120
INDEX_WIDTH=9
121+
MAX_WF_LENGTH=30
145122
WORKFLOW_COUNT_WIDTH=14
146123
GLOBAL_TOTAL_WIDTH=12
147-
148-
# Total table width
149124
TOTAL_WIDTH=$(( INDEX_WIDTH + 3 + MAX_WF_LENGTH + 3 + WORKFLOW_COUNT_WIDTH + 3 + GLOBAL_TOTAL_WIDTH ))
150125
126+
# Count total workflows for progress display
127+
TOTAL_WORKFLOWS=$(echo "$WORKFLOWS" | jq -r '. | length')
128+
151129
# Function to print dynamic table headers padded with '=' and spaces
152130
print_header() {
153131
local name="$1"
@@ -173,48 +151,51 @@ jobs:
173151
"$WORKFLOW_COUNT_WIDTH" "$(printf '%.0s-' $(seq 1 $WORKFLOW_COUNT_WIDTH))" \
174152
"$GLOBAL_TOTAL_WIDTH" "$(printf '%.0s-' $(seq 1 $GLOBAL_TOTAL_WIDTH))"
175153
176-
# Process each workflow by name
177-
for i in "${!WORKFLOW_NAMES_ARRAY[@]}"; do
154+
# Loop over deleted workflows JSON
155+
echo "$WORKFLOWS" | jq -c '.[]' | while read -r wf; do
156+
CURRENT_INDEX=$((CURRENT_INDEX + 1))
157+
WORKFLOW_NAME=$(echo "$wf" | jq -r '.name')
158+
WORKFLOW_ID=$(echo "$wf" | jq -r '.databaseId')
159+
WORKFLOW_PATH=$(echo "$wf" | jq -r '.path')
160+
161+
# Safety checks
162+
if [ -z "$WORKFLOW_NAME" ]; then
163+
echo "::error title=Workflow name empty::Resolved workflow name is empty at index $CURRENT_INDEX"
164+
exit 1
165+
fi
166+
if [ -z "$WORKFLOW_ID" ]; then
167+
echo "::error title=Workflow ID missing::Workflow '$WORKFLOW_NAME' (path: $WORKFLOW_PATH) has no ID"
168+
exit 1
169+
fi
178170
179-
WORKFLOW_NAME=${WORKFLOW_NAMES_ARRAY[$i]}
180-
[ -z "$WORKFLOW_NAME" ] && continue
181-
CURRENT_INDEX=$((i + 1))
182171
WORKFLOW_COUNT=0
183-
184-
WORKFLOW_ID=$(gh workflow list --all --json id,name \
185-
--jq ".[] | select(.name==\"$WORKFLOW_NAME\") | .id")
186-
187-
# GraphQL pagination variables
188172
AFTER_CURSOR=null
189173
174+
# Paginate over workflow runs
190175
while true; do
191176
RESPONSE=$(gh api graphql -F workflowId="$WORKFLOW_ID" -F after="$AFTER_CURSOR" \
192177
-f query='query($workflowId: ID!, $after: String) {
193178
node(id: $workflowId) {
194179
... on Workflow {
195180
runs(first: 100, after: $after) {
196-
pageInfo {
197-
hasNextPage
198-
endCursor
199-
}
200-
nodes {
201-
databaseId
202-
}
181+
pageInfo { hasNextPage endCursor }
182+
nodes { databaseId }
203183
}
204184
}
205185
}
206186
}')
207-
RUN_IDS=$(echo "$RESPONSE" | jq -r '.data.repository.workflowRuns.nodes[].databaseId')
208-
HAS_NEXT=$(echo "$RESPONSE" | jq -r '.data.repository.workflowRuns.pageInfo.hasNextPage')
209-
AFTER_CURSOR=$(echo "$RESPONSE" | jq -r '.data.repository.workflowRuns.pageInfo.endCursor')
187+
188+
RUN_IDS=$(echo "$RESPONSE" | jq -r '.data.node.runs.nodes[].databaseId')
189+
HAS_NEXT=$(echo "$RESPONSE" | jq -r '.data.node.runs.pageInfo.hasNextPage')
190+
AFTER_CURSOR=$(echo "$RESPONSE" | jq -r '.data.node.runs.pageInfo.endCursor')
210191
211192
[ -z "$RUN_IDS" ] && break
212193
213194
BATCH_COUNT=$(echo "$RUN_IDS" | wc -l | tr -d ' ')
214195
WORKFLOW_COUNT=$((WORKFLOW_COUNT + BATCH_COUNT))
215196
TOTAL_AFFECTED=$((TOTAL_AFFECTED + BATCH_COUNT))
216197
217-
# Print progress line
198+
# Print progress
218199
printf "%*s | %-*s | %*s | %*s\n" \
219200
"$INDEX_WIDTH" "[$CURRENT_INDEX/$TOTAL_WORKFLOWS]" \
220201
"$MAX_WF_LENGTH" "$WORKFLOW_NAME" \
@@ -223,30 +204,15 @@ jobs:
223204
224205
if [ "$MODE" = "execute" ]; then
225206
for RUN_ID in $RUN_IDS; do
226-
echo | gh run delete "$RUN_ID" >/dev/null
207+
gh run delete "$RUN_ID" >/dev/null
227208
done
228209
fi
229210
230211
[ "$HAS_NEXT" != "true" ] && break
231212
232-
# TEMPORARY break for testing large workflows
213+
# TEMPORARY safety break
233214
if [ "$WORKFLOW_COUNT" -gt 200 ]; then
234215
echo " ⚠️ Temporary break: workflow count exceeded 200, stopping early."
235216
break
236217
fi
237218
done
238-
239-
SUMMARY+=("$WORKFLOW_NAME|$WORKFLOW_COUNT")
240-
done
241-
242-
# === Summary Header ===
243-
print_header "Workflow Cleanup Summary"
244-
printf "%*s | %-*s | %-*s | %-*s\n" \
245-
"$INDEX_WIDTH" "" \
246-
"$MAX_WF_LENGTH" "Workflow" \
247-
"$WORKFLOW_COUNT_WIDTH" "Runs" \
248-
"$GLOBAL_TOTAL_WIDTH" ""
249-
printf "%*s-+-%-*s-+-%-*s-+-%-*s\n" \
250-
"$INDEX_WIDTH" "$(printf '%.0s-' $(seq 1 $INDEX_WIDTH))" \
251-
"$MAX_WF_LENGTH" "$(printf '%.0s-' $(seq 1 $MAX_WF_LENGTH))" \
252-
"$WORKFLOW_COUNT_WIDT

0 commit comments

Comments
 (0)