Skip to content

Commit 966bada

Browse files
authored
chore: auto-resubmit IETF draft before expiry (#182)
1 parent a8eb2e1 commit 966bada

4 files changed

Lines changed: 186 additions & 3 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Resubmit IETF Draft
2+
3+
# IETF I-Ds expire after 185 days (~6 months).
4+
# This checks weekly and opens a version-bump PR once 165 days have passed.
5+
# Merging the PR triggers submit-draft.yml which submits to the IETF
6+
# datatracker automatically. An author must then confirm via email.
7+
8+
on:
9+
schedule:
10+
# Check weekly; the job skips unless 165+ days since last revision bump
11+
- cron: "0 12 * * 1"
12+
workflow_dispatch:
13+
14+
permissions:
15+
contents: write
16+
pull-requests: write
17+
18+
jobs:
19+
bump-and-pr:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Check if 165+ days since last bump
27+
id: check
28+
run: |
29+
SPEC=$(find specs/core -name 'draft-httpauth-payment-*.md' | head -1)
30+
LAST_TOUCH=$(git log -1 --format=%ct -- "$SPEC")
31+
NOW=$(date +%s)
32+
DAYS_AGO=$(( (NOW - LAST_TOUCH) / 86400 ))
33+
echo "days_since_bump=$DAYS_AGO" >> "$GITHUB_OUTPUT"
34+
if [[ "$DAYS_AGO" -lt 165 ]]; then
35+
echo "Only $DAYS_AGO days since last bump — skipping (threshold: 165)"
36+
echo "skip=true" >> "$GITHUB_OUTPUT"
37+
else
38+
echo "$DAYS_AGO days since last bump — time to resubmit"
39+
echo "skip=false" >> "$GITHUB_OUTPUT"
40+
fi
41+
42+
- name: Bump revision
43+
if: steps.check.outputs.skip == 'false'
44+
id: bump
45+
run: |
46+
chmod +x scripts/bump_and_rename.sh
47+
NEW_VER=$(scripts/bump_and_rename.sh)
48+
echo "new_ver=$NEW_VER" >> "$GITHUB_OUTPUT"
49+
50+
- name: Create PR
51+
if: steps.check.outputs.skip == 'false'
52+
env:
53+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
run: |
55+
BRANCH="ietf/resubmit-${{ steps.bump.outputs.new_ver }}"
56+
git config user.name "github-actions[bot]"
57+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
58+
git checkout -b "$BRANCH"
59+
git add -A
60+
git commit -m "chore: bump draft revision to -${{ steps.bump.outputs.new_ver }}"
61+
git push origin "$BRANCH"
62+
gh pr create \
63+
--title "chore: bump IETF draft to revision -${{ steps.bump.outputs.new_ver }}" \
64+
--body "Automated revision bump to prevent the IETF Internet-Draft from expiring (185-day limit).
65+
66+
Merging this PR will automatically submit the new revision to the IETF datatracker.
67+
An author must then confirm via the email sent by the IETF." \
68+
--base main

.github/workflows/submit-draft.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Submit Draft to IETF
2+
3+
# Automatically submits the core spec to the IETF datatracker when a version
4+
# bump lands on main. One of the listed authors must still confirm via email.
5+
6+
on:
7+
push:
8+
branches: [main]
9+
paths:
10+
- "specs/core/draft-httpauth-payment-*.md"
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
submit:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
20+
21+
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
22+
23+
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
24+
with:
25+
context: .
26+
load: true
27+
tags: ietf-spec-tools:latest
28+
cache-from: type=gha
29+
cache-to: type=gha,mode=max
30+
31+
- name: Build XML
32+
run: |
33+
mkdir -p .cache
34+
docker run --rm --user $(id -u):$(id -g) -e HOME=/data \
35+
-v ${{ github.workspace }}:/data ietf-spec-tools:latest /data/scripts/gen.sh
36+
37+
- name: Detect spec version
38+
id: detect
39+
run: |
40+
SPEC=$(find specs/core -name 'draft-httpauth-payment-*.md' | head -1)
41+
DOCNAME=$(grep '^docname:' "$SPEC" | awk '{print $2}')
42+
echo "docname=$DOCNAME" >> "$GITHUB_OUTPUT"
43+
echo "Submitting $DOCNAME"
44+
45+
- name: Submit to IETF datatracker
46+
run: |
47+
RESPONSE=$(curl -s -w "\n%{http_code}" \
48+
-F "user=${{ secrets.IETF_USER }}" \
49+
-F "xml=@artifacts/${{ steps.detect.outputs.docname }}.xml" \
50+
https://datatracker.ietf.org/api/submission)
51+
52+
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
53+
BODY=$(echo "$RESPONSE" | sed '$d')
54+
55+
echo "$BODY" | jq . 2>/dev/null || echo "$BODY"
56+
57+
if [[ "$HTTP_CODE" -ge 400 ]]; then
58+
echo "::error::Submission failed with HTTP $HTTP_CODE"
59+
exit 1
60+
fi
61+
62+
STATUS_URL=$(echo "$BODY" | jq -r '.status_url // empty')
63+
if [[ -n "$STATUS_URL" ]]; then
64+
echo "Polling status at $STATUS_URL"
65+
for i in $(seq 1 10); do
66+
sleep 5
67+
STATE=$(curl -s "$STATUS_URL" | jq -r '.state')
68+
echo " Attempt $i: state=$STATE"
69+
if [[ "$STATE" != "validating" ]]; then
70+
break
71+
fi
72+
done
73+
fi
74+
75+
echo "::notice::Submission complete — an author must confirm via email."

scripts/bump_and_rename.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
# bump_and_rename.sh — Increment the core spec's revision number.
3+
#
4+
# Renames the file and updates frontmatter (docname, version) so the build
5+
# pipeline produces an artifact ready for IETF datatracker submission.
6+
#
7+
# Usage: ./scripts/bump_and_rename.sh
8+
# Prints the new version (e.g. "01") to stdout.
9+
set -euo pipefail
10+
11+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12+
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
13+
CORE_DIR="$ROOT_DIR/specs/core"
14+
15+
PREFIX="draft-httpauth-payment"
16+
17+
# Find the current spec file
18+
CURRENT_FILE=$(find "$CORE_DIR" -name "${PREFIX}-*.md" -type f | head -1)
19+
if [[ -z "$CURRENT_FILE" ]]; then
20+
echo "ERROR: Cannot find ${PREFIX}-*.md in $CORE_DIR" >&2
21+
exit 1
22+
fi
23+
24+
# Extract current version
25+
CURRENT_VER=$(basename "$CURRENT_FILE" .md | grep -oE '[0-9]+$')
26+
NEW_VER=$(printf "%02d" $((10#$CURRENT_VER + 1)))
27+
28+
NEW_FILE="$CORE_DIR/${PREFIX}-${NEW_VER}.md"
29+
30+
# Rename the file
31+
git -C "$ROOT_DIR" mv "$CURRENT_FILE" "$NEW_FILE"
32+
33+
# Update frontmatter version and docname
34+
sed -i.bak "s/^docname: .*$/docname: ${PREFIX}-${NEW_VER}/" "$NEW_FILE"
35+
sed -i.bak "s/^version: .*$/version: ${NEW_VER}/" "$NEW_FILE"
36+
rm -f "$NEW_FILE.bak"
37+
38+
echo "$NEW_VER"

scripts/lint_frontmatter.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ def lint_file(path: Path) -> list[str]:
2323
if field not in meta:
2424
errors.append(f"missing required field '{field}'")
2525

26-
# Check version format (can be string "00" or int 0)
26+
# Check version format (two-digit string like "00", "01", … or int 0)
2727
version = meta.get("version")
28-
if version not in ("00", 0):
29-
errors.append(f"version should be '00' or 0, got '{version}'")
28+
if not (isinstance(version, int) and 0 <= version <= 99) and not (
29+
isinstance(version, str) and len(version) == 2 and version.isdigit()
30+
):
31+
errors.append(f"version should be a two-digit revision (e.g. '00'), got '{version}'")
3032

3133
# Check title starts with capital letter
3234
title = meta.get("title", "")

0 commit comments

Comments
 (0)