Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .github/workflows/e2e-housekeeper.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: E2E Housekeeper

# ===========================================================================
# Source-of-truth E2E housekeeper workflow.
#
# This file is BOTH:
# - The workflow that runs in this repo (genlayer-e2e) for genlayer-
# e2e's own cache pool.
# - The file synced byte-identically to every consumer repo as
# `.github/workflows/e2e-housekeeper.yml` (sync-template.yaml owns
# the fan-out).
#
# Mirrors the architecture of e2e-pipeline.yml — one file in the source
# repo, copied verbatim to consumers, no wrapper layer. Adding a new
# scheduled upkeep step (artifact pruning, runner sweep, …) only needs
# editing this file; sync-template.yaml opens a PR in each consumer.
#
# Cache storage is per-repo, so the eviction step runs in the CALLER's
# context: `gh cache list` / `gh cache delete` operate on the caller's
# pool via the inherited GITHUB_TOKEN. The runner's filesystem starts
# empty, so step 1 checks out genlayer-e2e to access the extracted
# `evict-stale-caches.sh` script — github.token in a synced consumer
# context still has cross-org read access on the org's private repos.
# ===========================================================================

on:
schedule:
- cron: '0 6 * * *' # daily 06:00 UTC
# No inputs: production triggers (schedule today, PR-merged later)
# don't pass them, and the script's defaults (24h idle / 200 page
# cap) are stable. workflow_dispatch stays as a no-arg "run the
# cron now" button — handy in genlayer-e2e while iterating.
workflow_dispatch:

# Least-privilege. `evict-stale-caches.sh` invokes `gh cache list`
# (read) and `gh cache delete` (write) against the caller's cache pool
# via secrets.GITHUB_TOKEN. The GHA Cache API lives under the actions:
# permission namespace, so deletion requires actions:write. `contents:
# read` covers the checkout that fetches this repo's scripts.
permissions:
actions: write
contents: read

# Serialize runs so two overlapping firings (manual dispatch + schedule)
# don't both try to delete the same entry.
concurrency:
group: cache-cleanup
cancel-in-progress: false

jobs:
evict-stale:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# Pull the extracted script. Explicit `repository:` because — when
# this file is synced to a consumer — actions/checkout's default
# target is the CONSUMER's repo, not genlayer-e2e. github.token
# in the consumer context has org-wide read on private repos so
# the clone works without an App token.
- name: Checkout genlayer-e2e
uses: actions/checkout@v6
with:
repository: genlayerlabs/genlayer-e2e
token: ${{ github.token }}

- name: Delete idle caches
env:
# `gh cache delete` consumes GH_TOKEN. github.repository
# resolves to the caller's repo (where the cron fires + the
# cache pool lives).
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
run: ./taskfiles/housekeeper/scripts/evict-stale-caches.sh --age 24 --limit 200

# Companion sweep for artifacts (logs, shard outputs, per-component
# summaries). Same 24h idle window so the two sweeps stay in sync.
# `if: always()` so an early cache-sweep failure doesn't skip the
# artifact pass — they're independent.
- name: Delete idle artifacts
if: always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
run: ./taskfiles/housekeeper/scripts/evict-stale-artifacts.sh --age 24 --limit 1000
Loading