Skip to content

Commit f93eab3

Browse files
committed
workflows: Improve rev-tag-notifier message
1 parent 5dfb805 commit f93eab3

File tree

1 file changed

+134
-26
lines changed

1 file changed

+134
-26
lines changed

.github/workflows/rev-tag-notifier.yml

Lines changed: 134 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ permissions:
1010
jobs:
1111
increment-and-notify:
1212
runs-on: ubuntu-latest
13+
env:
14+
RETRY_MAX: 3
15+
COMMIT_LIMIT: 50 # max commits to include in Telegram message
1316
steps:
1417
- name: Checkout pushed ref (full)
1518
uses: actions/checkout@v4
1619
with:
17-
fetch-depth: 0 # needed to list tags and read history
20+
fetch-depth: 0
21+
token: ${{ secrets.GITHUB_TOKEN }}
1822

1923
- name: Configure git user
2024
run: |
@@ -27,12 +31,12 @@ jobs:
2731
# Pattern: rev-<number>
2832
latest=$(git tag --list 'rev-*' --sort=-v:refname | head -n1 || true)
2933
if [ -z "$latest" ]; then
30-
echo "::set-output name=latest::"
31-
echo "::set-output name=num::"
34+
echo "latest=" >> "$GITHUB_OUTPUT"
35+
echo "num=" >> "$GITHUB_OUTPUT"
3236
else
3337
num=${latest#rev-}
34-
echo "::set-output name=latest::$latest"
35-
echo "::set-output name=num::$num"
38+
echo "latest=$latest" >> "$GITHUB_OUTPUT"
39+
echo "num=$num" >> "$GITHUB_OUTPUT"
3640
fi
3741
3842
- name: Determine next rev number
@@ -50,46 +54,150 @@ jobs:
5054
fi
5155
fi
5256
tag="rev-${next}"
53-
echo "::set-output name=tag::$tag"
54-
echo "::set-output name=number::$next"
57+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
58+
echo "number=$next" >> "$GITHUB_OUTPUT"
5559
56-
- name: Create and push rev tag
60+
- name: Create and push rev tag (with retry to avoid race)
61+
id: push_tag
5762
env:
5863
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5964
run: |
60-
tag="${{ steps.next_rev.outputs.tag }}"
61-
echo "Creating tag $tag at $GITHUB_SHA"
62-
git tag "$tag" "$GITHUB_SHA"
63-
git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git" "refs/tags/${tag}"
65+
set -euo pipefail
66+
attempt=0
67+
# Determine target SHA to tag (prefer GITHUB_SHA if valid, else HEAD)
68+
target_sha="${GITHUB_SHA:-}"
69+
if ! git rev-parse --verify "$target_sha" >/dev/null 2>&1; then
70+
target_sha=$(git rev-parse --verify HEAD)
71+
fi
72+
73+
while [ $attempt -lt "$RETRY_MAX" ]; do
74+
attempt=$((attempt + 1))
75+
# Recompute latest to reduce window-of-time races
76+
latest=$(git tag --list 'rev-*' --sort=-v:refname | head -n1 || true)
77+
if [ -z "$latest" ]; then
78+
num=0
79+
else
80+
num=${latest#rev-}
81+
if ! echo "$num" | grep -Eq '^[0-9]+$'; then
82+
num=0
83+
fi
84+
fi
85+
next=$((num + 1))
86+
tag="rev-${next}"
87+
echo "Attempt $attempt: creating tag $tag at $target_sha"
88+
89+
# Create annotated tag (safer metadata) and push
90+
git tag -a "$tag" -m "Auto increment rev tag ${tag}" "$target_sha"
91+
if git push origin "refs/tags/${tag}"; then
92+
echo "pushed_tag=$tag" >> "$GITHUB_OUTPUT"
93+
echo "pushed=1" >> "$GITHUB_OUTPUT"
94+
exit 0
95+
else
96+
echo "Push failed (possible collision). Deleting local tag and retrying."
97+
git tag -d "$tag" || true
98+
sleep 1
99+
fi
100+
done
101+
102+
echo "pushed=" >> "$GITHUB_OUTPUT"
103+
echo "pushed_tag=" >> "$GITHUB_OUTPUT"
104+
echo "Failed to create tag after $RETRY_MAX attempts."
105+
exit 1
64106
65107
- name: Find latest rev tag (by creation date for notification)
66108
id: latest_for_notify
67109
run: |
68-
# find latest rev-* tag by creation date; leave empty if none
110+
# Ensure tags are available
111+
git fetch --tags --prune
112+
# find latest rev-* tag by creation date; prefer annotated tag taggerdate, fall back to commit date
69113
entry=$(git for-each-ref --sort=-creatordate --format='%(refname:short) %(creatordate:unix)' refs/tags | grep '^rev-[0-9]\+' | head -n1 || true)
70114
if [ -z "$entry" ]; then
71-
echo "::set-output name=tag::"
72-
echo "::set-output name=ts::"
115+
echo "tag=" >> "$GITHUB_OUTPUT"
116+
echo "ts=" >> "$GITHUB_OUTPUT"
73117
else
74118
tag=$(echo "$entry" | awk '{print $1}')
75119
ts=$(echo "$entry" | awk '{print $2}')
76-
echo "::set-output name=tag::$tag"
77-
echo "::set-output name=ts::$ts"
120+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
121+
echo "ts=$ts" >> "$GITHUB_OUTPUT"
78122
fi
79123
80124
- name: Build Telegram message
81125
id: message
82126
run: |
127+
set -euo pipefail
83128
repo="${GITHUB_REPOSITORY}"
84-
branch="${GITHUB_REF#refs/heads/}"
85-
sha_full="${GITHUB_SHA}"
86-
sha="${sha_full::7}"
87-
author="$(git --no-pager show -s --format='%an' $GITHUB_SHA || echo '')"
88-
msg="$(git --no-pager show -s --format='%s' $GITHUB_SHA || echo '')"
129+
repo_url="https://github.com/${repo}"
130+
ref="${GITHUB_REF:-}"
131+
branch=""
132+
pushed_tag=""
133+
if echo "$ref" | grep -q '^refs/heads/'; then
134+
branch="${ref#refs/heads/}"
135+
elif echo "$ref" | grep -q '^refs/tags/'; then
136+
pushed_tag="${ref#refs/tags/}"
137+
branch=""
138+
else
139+
branch="$ref"
140+
fi
141+
142+
sha_full="${GITHUB_SHA:-$(git rev-parse --verify HEAD)}"
143+
sha_short="${sha_full::7}"
144+
89145
latest_tag="${{ steps.latest_for_notify.outputs.tag }}"
90-
tag_part="Rev: ${latest_tag:-(none)}"
91-
body="Repo: ${repo}%0ABranch: ${branch}%0ACommit: ${sha}%0AAuthor: ${author}%0AMessage: ${msg}%0A${tag_part}"
92-
echo "::set-output name=body::$body"
146+
147+
before="${GITHUB_EVENT_BEFORE:-}"
148+
after="${GITHUB_EVENT_AFTER:-$GITHUB_SHA}"
149+
150+
# Build commits list safely using a unit separator
151+
if [ -n "$before" ] && [ "$before" != "0000000000000000000000000000000000000000" ]; then
152+
range="${before}..${after}"
153+
git_cmd=(git --no-pager log --pretty=format:'%h%x1F%an%x1F%s' "${range}" --max-count=${COMMIT_LIMIT})
154+
else
155+
git_cmd=(git --no-pager log -n 1 --pretty=format:'%h%x1F%an%x1F%s' "${after}")
156+
fi
157+
158+
commits_raw=$("${git_cmd[@]}" || true)
159+
160+
commits_text=""
161+
if [ -z "$commits_raw" ]; then
162+
commits_text="(no commits found)"
163+
else
164+
# iterate lines separated by newline
165+
while IFS= read -r line; do
166+
# split on unit separator
167+
IFS=$'\x1F' read -r shorthash author message <<< "$line"
168+
# resolve full hash where possible
169+
fullhash=$(git rev-parse "${shorthash}" 2>/dev/null || echo "${shorthash}")
170+
commit_url="${repo_url}/commit/${fullhash}"
171+
# escape HTML entities for Telegram parse_mode=HTML
172+
esc_msg=$(printf '%s' "$message" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')
173+
esc_author=$(printf '%s' "$author" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')
174+
commits_text="${commits_text}${shorthash} - ${esc_msg} (${esc_author})%0A${commit_url}%0A"
175+
done <<< "$commits_raw"
176+
fi
177+
178+
repo_link="<a href=\"${repo_url}\">${repo}</a>"
179+
commit_link="<a href=\"${repo_url}/commit/${sha_full}\">${sha_short}</a>"
180+
181+
tag_link="(none)"
182+
if [ -n "${latest_tag}" ]; then
183+
tag_link="<a href=\"${repo_url}/releases/tag/${latest_tag}\">${latest_tag}</a>"
184+
fi
185+
186+
branch_info=""
187+
if [ -n "$branch" ]; then
188+
branch_info="Branch: ${branch}%0A"
189+
elif [ -n "$pushed_tag" ]; then
190+
branch_info="Tag push: ${pushed_tag}%0A"
191+
fi
192+
193+
body="Repo: ${repo_link}%0A${branch_info}Commit: ${commit_link}%0ATag: ${tag_link}%0A%0ACommits:%0A${commits_text}"
194+
# Truncate body if excessively long (Telegram has limits ~4096 chars)
195+
maxlen=3800
196+
if [ "${#body}" -gt "$maxlen" ]; then
197+
body="${body:0:$maxlen}%0A...(truncated)"
198+
fi
199+
200+
echo "body=$body" >> "$GITHUB_OUTPUT"
93201
94202
- name: Send Telegram notification
95203
env:
@@ -108,4 +216,4 @@ jobs:
108216
109217
- name: Output created tag
110218
run: |
111-
echo "Created tag: ${{ steps.next_rev.outputs.tag }}"
219+
echo "Created tag: ${{ steps.push_tag.outputs.pushed_tag }}"

0 commit comments

Comments
 (0)