-
Notifications
You must be signed in to change notification settings - Fork 45
264 lines (229 loc) · 11.5 KB
/
track-publishes.yml
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
name: Track Publishes
on:
schedule:
- cron: "0/5 * * * *"
workflow_dispatch:
permissions:
actions: read # required to access workflow runs
contents: write # required to access the repository, for the dispatch event
env:
ADD_MD_SUFFIX: "true" # default value for all triggers, this is a compatibility fix for older workflows
REPOSITORY_DISPATCH_EVENT: "resource-published-native" # default value for all triggers, this is a compatibility fix for older workflows
WORKFLOW_CALL_USE: "example" # if REPOSITORY_DISPATCH_EVENT is unset, this is the workflow file that will be called
ROUTE_FILTER: "live" # filter for the route field in the logs, can be 'live' or 'preview'
jobs:
check-token-expiry:
runs-on: ubuntu-latest
steps:
- name: Check JWT token expiration
run: |
# Function to decode JWT token part
decode_base64_url() {
local len=$((${#1} % 4))
local result="$1"
if [ $len -eq 2 ]; then result="$1"'=='
elif [ $len -eq 3 ]; then result="$1"'='
fi
echo "$result" | tr '_-' '/+' | base64 -d
}
# Get the token
TOKEN="${{ secrets.AEM_LIVE_ADMIN_TOKEN }}"
# Extract the payload (second part of the JWT)
PAYLOAD=$(echo -n $TOKEN | cut -d '.' -f 2)
# Decode the payload
DECODED_PAYLOAD=$(decode_base64_url $PAYLOAD)
# Extract expiration timestamp
EXPIRY=$(echo $DECODED_PAYLOAD | jq -r .exp)
CURRENT_TIME=$(date +%s)
ONE_WEEK_FROM_NOW=$((CURRENT_TIME + 7*24*60*60))
echo "Token expires at: $(date -d @$EXPIRY)"
echo "Current time: $(date -d @$CURRENT_TIME)"
echo "One week from now: $(date -d @$ONE_WEEK_FROM_NOW)"
if [ $EXPIRY -lt $ONE_WEEK_FROM_NOW ]; then
echo "::warning::AEM_LIVE_ADMIN_TOKEN will expire in less than a week (on $(date -d @$EXPIRY)). Please renew the token soon."
echo "Token expiration is approaching" >> $GITHUB_STEP_SUMMARY
echo "The AEM_LIVE_ADMIN_TOKEN will expire on $(date -d @$EXPIRY)" >> $GITHUB_STEP_SUMMARY
echo "Please generate a new token and update the repository secret." >> $GITHUB_STEP_SUMMARY
fi
if [ $EXPIRY -lt $CURRENT_TIME ]; then
echo "::error::AEM_LIVE_ADMIN_TOKEN has expired on $(date -d @$EXPIRY)"
exit 1
fi
check-last-run:
runs-on: ubuntu-latest
outputs:
workflow-id: ${{ steps.workflow-id.outputs.WORKFLOW_ID }}
last-run-iso: ${{ steps.last-run.outputs.LAST_CREATED_AT_ISO }} # ISO 8601
last-run-unix: ${{ steps.last-run.outputs.LAST_CREATED_AT_UNIX }} # Unix timestamp
branch-name: ${{ steps.branch-name.outputs.BRANCH_NAME }}
steps:
- name: Get branch name
id: branch-name
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [[ ${GITHUB_EVENT_NAME} == "pull_request" ]]
then
echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_OUTPUT
else
echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
fi
- name: Get workflow id
id: workflow-id
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
WORKFLOW_ID=$(gh api /repos/${{ github.repository }}/actions/runs/${{ github.run_id }} | jq -r .workflow_id)
echo "WORKFLOW_ID=$WORKFLOW_ID" >> $GITHUB_OUTPUT
echo "Workflow id: ${WORKFLOW_ID}"
- name: Get previous build status
shell: bash
id: last-run
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MAX_PAGES: "5" # Maximum number of pages to check before giving up
run: |
LAST_CREATED_AT_ISO=""
page=1
while [[ $page -le $MAX_PAGES ]]; do
echo "Checking page $page for successful runs..."
# Get workflow runs for current page
WORKFLOW_RUNS=$(gh api "/repos/${{ github.repository }}/actions/workflows/${{ steps.workflow-id.outputs.WORKFLOW_ID }}/runs?status=completed&branch=${{ steps.branch-name.outputs.BRANCH_NAME }}&page=$page&per_page=100")
# Check if we got any runs
TOTAL_COUNT=$(echo "$WORKFLOW_RUNS" | jq '.total_count')
if [[ $TOTAL_COUNT -eq 0 || $(echo "$WORKFLOW_RUNS" | jq '.workflow_runs | length') -eq 0 ]]; then
echo "No more workflow runs found."
break
fi
# Try to find a successful run on this page
LAST_CREATED_AT_ISO=$(echo "$WORKFLOW_RUNS" | jq -r "[.workflow_runs[] | select(.conclusion == \"success\") | .created_at][0]")
if [[ "$LAST_CREATED_AT_ISO" != "null" ]]; then
echo "Found successful run on page $page"
break
fi
# Store first run's timestamp as fallback if we haven't stored one yet
if [[ $page -eq 1 ]]; then
FALLBACK_TIMESTAMP=$(echo "$WORKFLOW_RUNS" | jq -r "[.workflow_runs[].created_at][0]")
if [[ "$FALLBACK_TIMESTAMP" != "null" ]]; then
echo "Storing fallback timestamp from first page: $FALLBACK_TIMESTAMP"
FIRST_RUN_ISO=$FALLBACK_TIMESTAMP
fi
fi
((page++))
done
# If we didn't find a successful run, use fallback strategies
if [[ "$LAST_CREATED_AT_ISO" == "null" || -z "$LAST_CREATED_AT_ISO" ]]; then
echo "::warning::No successful workflow runs found in the last $MAX_PAGES pages."
if [[ -n "$FIRST_RUN_ISO" ]]; then
echo "Using timestamp from earliest found run as fallback"
LAST_CREATED_AT_ISO=$FIRST_RUN_ISO
# Add information about recent failures to the job summary
echo "Recent workflow run history:" >> $GITHUB_STEP_SUMMARY
echo "$WORKFLOW_RUNS" | jq -r '.workflow_runs | map({conclusion, created_at, html_url}) | .[:5]' >> $GITHUB_STEP_SUMMARY
else
echo "::warning::No previous runs found at all. Using a timestamp from 5 minutes ago as fallback."
LAST_CREATED_AT_ISO=$(date -u -d "5 minutes ago" "+%Y-%m-%dT%H:%M:%SZ")
fi
fi
LAST_CREATED_AT_UNIX=$(date -d "$LAST_CREATED_AT_ISO" +%s)
echo "LAST_CREATED_AT_ISO=$LAST_CREATED_AT_ISO" >> $GITHUB_OUTPUT
echo "LAST_CREATED_AT_UNIX=$LAST_CREATED_AT_UNIX" >> $GITHUB_OUTPUT
echo "Previous build created at: $LAST_CREATED_AT_ISO"
poll-log:
runs-on: ubuntu-latest
needs: check-last-run
steps:
- name: Check for required secrets
run: |
if [[ -z "${{ secrets.AEM_LIVE_ADMIN_TOKEN }}" ]]; then
echo "::error::The AEM_LIVE_ADMIN_TOKEN secret is not configured. Please add this secret to your repository settings."
exit 1
fi
- name: Get Logs
id: get-logs
run: |
echo "Debug: Last run ISO: ${{ needs.check-last-run.outputs.last-run-iso }}"
# URL encode the from parameter (using tr to remove newlines)
FROM_PARAM=$(echo -n "${{ needs.check-last-run.outputs.last-run-iso }}" | tr -d '\n' | jq -sRr @uri)
echo "Debug: URL encoded from parameter: $FROM_PARAM"
# Construct and echo the full URL for debugging
FULL_URL="https://admin.hlx.page/log/adobe/helix-website/main?from=$FROM_PARAM"
echo "Debug: Full URL: $FULL_URL"
# Make the API request
RESPONSE=$(curl --http1.1 -s -w "\n%{http_code}" \
-H "Authorization: token $(echo -n "${{ secrets.AEM_LIVE_ADMIN_TOKEN }}" | tr -d '\n')" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Agent: GitHub-Actions-Workflow" \
"$FULL_URL")
# Extract status code from last line
HTTP_STATUS=$(echo "$RESPONSE" | tail -n1)
# Extract response body (everything except the last line)
BODY=$(echo "$RESPONSE" | sed '$ d')
echo "Debug: HTTP Status: $HTTP_STATUS"
# Check if status code is not 2xx
if [[ $HTTP_STATUS -lt 200 ]] || [[ $HTTP_STATUS -gt 299 ]]; then
echo "Error: API request failed with status $HTTP_STATUS"
echo "Response body: $BODY"
exit 1
fi
# Process the response if status was ok
LOGS=$(echo "$BODY" | jq -R --arg route "${{ env.ROUTE_FILTER }}" 'fromjson | .entries | sort_by(.timestamp) | map(select(.route == $route))' | base64 -w 0)
echo "Debug: LOGS value length: ${#LOGS}"
echo "Debug: First few characters: ${LOGS:0:100}"
echo "logs=$LOGS" >> $GITHUB_OUTPUT
- name: Check for publishes
id: check-publishes
if: steps.get-logs.outputs.logs != 'W10K'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
LOGS="${{ steps.get-logs.outputs.logs }}"
echo "$LOGS" | base64 -d | jq -c '.[]' | while read -r log; do
user=$(echo "$log" | jq -r '.user // "unknown"')
status=$(echo "$log" | jq -r '.status')
timestamp=$(echo "$log" | jq -r '.timestamp')
# Get all paths (combine path and paths, filter out empty strings)
paths=$(echo "$log" | jq -r '[ .path, (.paths[]?) ] | map(select(length > 0))[]')
echo "$paths" | while read -r path; do
# Add .md extension if configured and path has no extension
if [[ "${{ env.ADD_MD_SUFFIX }}" == "true" ]] && [[ "$path" != *.* ]]; then
path="${path}.md"
fi
# Handle repository dispatch or workflow call
if [[ -n "${{ env.REPOSITORY_DISPATCH_EVENT }}" ]]; then
payload=$(jq -n \
--arg type "${{ env.REPOSITORY_DISPATCH_EVENT }}" \
--arg path "$path" \
--arg user "$user" \
--arg timestamp "$timestamp" \
--arg status "$status" \
'{
event_type: $type,
client_payload: {
path: $path,
user: $user,
timestamp: $timestamp,
status: $status
}
}')
echo "Triggering dispatch for $path with event type: ${{ env.REPOSITORY_DISPATCH_EVENT }}"
gh api \
--method POST \
--header "Accept: application/vnd.github.v3+json" \
"/repos/${{ github.repository }}/dispatches" \
--input - <<< "$payload"
elif [[ -n "${{ env.WORKFLOW_CALL_USE }}" ]]; then
echo "Triggering workflow ${{ env.WORKFLOW_CALL_USE }} for $path"
gh workflow run "${{ env.WORKFLOW_CALL_USE }}" \
-f path="$path" \
-f user="$user" \
-f timestamp="$timestamp" \
-f status="$status"
else
echo "Skipping triggers for $path (neither REPOSITORY_DISPATCH_EVENT nor WORKFLOW_CALL_USE is set)"
fi
done
done