fix(ci): persist Hacktoberfest tracker via a PR (protected-branch push was silently failing) #10
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 }} |