Skip to content

Refresh insights

Refresh insights #145

name: Refresh insights
# Re-runs the on-chain analytics pipeline and force-pushes everything (the
# gzipped events+versions caches and the rebuilt insights JSON) to the orphan
# `insights-cache` branch as a single rolling commit. The frontend fetches
# the JSON at runtime via jsdelivr against this branch, so the deployed site
# picks up new data without a rebuild and without us needing to push to a
# protected main branch.
#
# Daily flow:
# 1. Restore .cache/ from insights-cache (git archive | tar -x).
# 2. Run analytics pipeline incrementally.
# 3. Force-push refreshed .cache/ + insights-mainnet.json back to
# insights-cache as one rolling commit.
on:
schedule:
- cron: "0 3 * * *" # daily 03:00 UTC
workflow_dispatch:
permissions:
contents: write
concurrency:
group: refresh-insights
cancel-in-progress: false
env:
CACHE_BRANCH: insights-cache
CACHE_DIR: packages/contracts/scripts/analytics/.cache
INSIGHTS_JSON: apps/frontend/src/data/insights-mainnet.json
jobs:
refresh:
runs-on: ubuntu-latest
timeout-minutes: 60
env:
VITE_APP_ENV: mainnet
# Hardhat needs a valid mnemonic to derive accounts for the vechain_mainnet
# network config. The analytics scripts are read-only and never sign or
# send transactions, so the standard hardhat test mnemonic is safe here.
MNEMONIC: "test test test test test test test test test test test junk"
# vechain.energy gives us higher throughput / fewer drops than the
# public mainnet.vechain.org RPC during heavy event + balance scans.
THOR_NODE_URL: https://node-mainnet.vechain.energy
steps:
- name: Checkout main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
cache: yarn
- name: Restore analytics cache from insights-cache branch
env:
BRANCH: ${{ env.CACHE_BRANCH }}
DIR: ${{ env.CACHE_DIR }}
run: |
mkdir -p "$DIR"
if git ls-remote --exit-code --heads origin "$BRANCH" > /dev/null 2>&1; then
git fetch --depth 1 origin "$BRANCH":"$BRANCH"
# Stream the gzipped cache files out of the branch without switching HEAD.
git archive "$BRANCH" | tar -x
echo "Restored cache from $BRANCH:"
ls -lh "$DIR" || true
else
echo "::warning::Cache branch '$BRANCH' does not exist."
echo "Run 'yarn contracts:analyze:mainnet' locally, then push the"
echo "$DIR contents to the '$BRANCH' branch to skip cold start."
fi
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run analytics pipeline
env:
NODE_OPTIONS: "--max-old-space-size=6144"
run: |
yarn contracts:analyze:mainnet
yarn contracts:export-insights:mainnet
- name: Push refreshed cache + insights JSON to insights-cache branch
env:
BRANCH: ${{ env.CACHE_BRANCH }}
DIR: ${{ env.CACHE_DIR }}
JSON: ${{ env.INSIGHTS_JSON }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# Build the cache-branch state in an isolated worktree so the main
# checkout stays untouched. The branch holds two kinds of artifacts:
# - .cache/*.json.gz : seed for the next run's incremental fetch
# - apps/frontend/src/data/insights-mainnet.json : served via
# jsdelivr to the live site
# Both live here to sidestep main's branch protection rule (direct
# pushes are forbidden).
WT=$(mktemp -d)
git worktree add --detach "$WT"
find "$WT" -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
mkdir -p "$WT/$DIR"
cp -R "$DIR"/. "$WT/$DIR"/
mkdir -p "$WT/$(dirname "$JSON")"
cp "$JSON" "$WT/$JSON"
(
cd "$WT"
git checkout --orphan rolling
git add -f "$DIR" "$JSON"
if git diff --cached --quiet; then
echo "No changes; skipping push."
else
git commit -m "chore(insights-cache): refresh $(date -u +%Y-%m-%dT%H:%M:%SZ)"
# Single rolling commit, no history bloat.
git push --force origin "rolling:$BRANCH"
fi
)
git worktree remove --force "$WT"