Skip to content

fix(ci): persist Hacktoberfest tracker via a PR (protected-branch push was silently failing) #10

fix(ci): persist Hacktoberfest tracker via a PR (protected-branch push was silently failing)

fix(ci): persist Hacktoberfest tracker via a PR (protected-branch push was silently failing) #10

# Daily refresh of the Hacktoberfest 2026 open-PR cleanup tracker.
# Ticks off any tracked pull request that has since been merged/closed, and
# rewrites the "Automated statistics" section (open issue/PR counts + the top
# three `awaiting reviews` directories). The job fails on purpose once
# Hacktoberfest 2026 has begun (>= 2026-10-01), which is the signal to retire it.
name: hacktoberfest_prep
on:
push:
paths:
- ".github/workflows/hacktoberfest_prep.yml"
- "scripts/hacktoberfest_prep_update.py"
pull_request:
paths:
- ".github/workflows/hacktoberfest_prep.yml"
- "scripts/hacktoberfest_prep_update.py"
schedule:
- cron: "50 11 * * *" # 11:50 UTC every day
workflow_dispatch: # allow a manual run while testing
permissions:
contents: write
pull-requests: write
jobs:
hacktoberfest-prep:
# No point running on forks — this pushes to the repo's own docs file.
if: github.repository == 'TheAlgorithms/Python'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version-file: .python-version
allow-prereleases: true
- name: Install dependencies
run: python -m pip install --upgrade "httpx2>=2.0.1"
- name: Update the tracker
id: update
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
# Don't let the intentional post-Oct-1 failure stop the commit step;
# capture the exit code and re-raise it after pushing any changes.
run: |
set +e
python scripts/hacktoberfest_prep_update.py
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
# Dry run on push / pull_request: show the diff the script produced but
# do NOT commit or push. This lets a PR prove the tracker still gathers
# its data and rewrites docs/hacktober_2026_prep.md correctly without
# leaving a permanent commit. Only the schedule/manual runs persist.
- name: Show changes (dry run)
if: github.event_name == 'push' || github.event_name == 'pull_request'
run: |
echo "Dry run (${{ github.event_name }}): showing git diff, not committing."
git --no-pager diff -- docs/hacktober_2026_prep.md
if git diff --quiet -- docs/hacktober_2026_prep.md; then
echo "No changes to docs/hacktober_2026_prep.md."
fi
# `master` is a protected branch: direct pushes are rejected with
# `GH006: Protected branch update failed ... Changes must be made through
# a pull request`. So instead of committing straight to master, persist
# the refreshed tracker by opening — or updating in place — a single
# rolling pull request. Re-runs reuse the same branch, so at most one
# open PR exists at any time.
- name: Open or update the tracker pull request
if: github.event_name != 'push' && github.event_name != 'pull_request'
uses: peter-evans/create-pull-request@v7
with:
add-paths: docs/hacktober_2026_prep.md
branch: chore/hacktoberfest-2026-prep-refresh
delete-branch: true
commit-message: "chore: refresh Hacktoberfest 2026 prep tracker"
title: "chore: refresh Hacktoberfest 2026 prep tracker"
body: |
Automated daily refresh of the Hacktoberfest 2026 open-PR cleanup
tracker (`docs/hacktober_2026_prep.md`): ticks off any tracked pull
request that has since been merged/closed and rewrites the
**Automated statistics** section.
This PR is updated in place by the `hacktoberfest_prep` workflow, so
it always reflects the latest scheduled run. Merge it whenever you
want to capture the current snapshot; a fresh one opens on the next
run if there are new changes.
- name: Propagate the script's exit code
run: exit ${{ steps.update.outputs.exit_code }}