Skip to content
Latchkey

Regenerate Hex API cassettes workflow (oliver-kriska/claude-elixir-phoenix)

The Regenerate Hex API cassettes workflow from oliver-kriska/claude-elixir-phoenix, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: oliver-kriska/claude-elixir-phoenix.github/workflows/cassette-regen.ymlLicense MITView source

What it does

This is the Regenerate Hex API cassettes workflow from the oliver-kriska/claude-elixir-phoenix repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Regenerate Hex API cassettes

# Monthly regeneration of VCR cassettes under
# plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/
# used by Rules 6 + 8 for offline smoke testing.
#
# Captures fresh response bodies from hex.pm, updates the _meta.json SHA
# index, and opens a PR. Falls back to a workflow artifact when org
# policy blocks GITHUB_TOKEN PR creation.

on:
  schedule:
    # 5th of month at 09:00 UTC (staggered from seed-regen on the 1st)
    - cron: '0 9 5 * *'
  workflow_dispatch:

jobs:
  regenerate:
    name: Regenerate hex-api cassettes
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'

      - name: Install jq (preinstalled on ubuntu-latest but pin explicit)
        run: jq --version

      - name: Regenerate cassettes for seed top-100 + smoke fixtures
        id: regen
        run: |
          set -u
          seed_list="plugins/elixir-phoenix/skills/deps-audit/smoke-test/corpus.d/benign-100.txt"
          if [ ! -f "${seed_list}" ]; then
            echo "::error::seed list missing: ${seed_list}"
            exit 1
          fi

          updated=0
          while IFS= read -r line; do
            pkg=$(echo "${line}" | awk '{print $1}')
            ver=$(echo "${line}" | awk '{print $2}')
            [ -z "${pkg}" ] && continue
            bash plugins/elixir-phoenix/skills/deps-audit/priv/cassettes/capture.sh \
              "${pkg}" "${ver}" \
              || echo "::warning::capture failed for ${pkg} ${ver}"
            updated=$((updated + 1))
          done < "${seed_list}"

          echo "updated_count=${updated}" >> "${GITHUB_OUTPUT}"

      - name: Detect cassette drift
        id: drift
        run: |
          # Diff the cassettes dir; empty diff means no PR needed
          if git diff --quiet plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/; then
            echo "drift=false" >> "${GITHUB_OUTPUT}"
            echo "No cassette drift this run."
          else
            echo "drift=true" >> "${GITHUB_OUTPUT}"
            git diff --stat plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/
          fi

      - name: Open PR (primary path)
        id: open_pr
        if: steps.drift.outputs.drift == 'true'
        continue-on-error: true
        uses: peter-evans/create-pull-request@v8
        with:
          commit-message: 'chore(cassettes): monthly hex-api regen'
          title: 'Monthly hex-api cassette regeneration'
          body: |
            Auto-generated PR refreshing VCR cassettes from `hex.pm/api`.

            **Review checklist:**
            - [ ] Diff per-cassette body for owner/release changes
            - [ ] `_meta.json` SHA entries updated for changed cassettes
            - [ ] No new package's owners list looks suspicious
            - [ ] `captured_at` matches today's date
          branch: chore/hex-api-cassette-regen
          labels: |
            cassette-regen
            security
            auto-pr

      - name: 403 fallback - upload as artifact
        if: steps.drift.outputs.drift == 'true' && steps.open_pr.outcome == 'failure'
        uses: actions/upload-artifact@v7
        with:
          name: cassettes-regen-${{ github.run_id }}
          path: plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/
          retention-days: 90

      - name: Job summary
        if: always()
        run: |
          {
            echo "## Cassette regeneration summary"
            echo
            echo "- Packages processed: ${{ steps.regen.outputs.updated_count }}"
            echo "- Drift detected: ${{ steps.drift.outputs.drift }}"
            if [ "${{ steps.drift.outputs.drift }}" = "true" ] && [ "${{ steps.open_pr.outcome }}" = "failure" ]; then
              echo "- **PR creation FAILED (likely 403).** Cassettes uploaded as"
              echo "  artifact \`cassettes-regen-${{ github.run_id }}\`."
              echo "- To enable PR creation: Settings → Actions → Allow GitHub"
              echo "  Actions to create and approve pull requests."
            elif [ "${{ steps.drift.outputs.drift }}" = "true" ]; then
              echo "- PR opened: chore/hex-api-cassette-regen"
            else
              echo "- No drift; no PR needed."
            fi
          } >> "${GITHUB_STEP_SUMMARY}"

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: Regenerate Hex API cassettes
 
# Monthly regeneration of VCR cassettes under
# plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/
# used by Rules 6 + 8 for offline smoke testing.
#
# Captures fresh response bodies from hex.pm, updates the _meta.json SHA
# index, and opens a PR. Falls back to a workflow artifact when org
# policy blocks GITHUB_TOKEN PR creation.
 
on:
  schedule:
    # 5th of month at 09:00 UTC (staggered from seed-regen on the 1st)
    - cron: '0 9 5 * *'
  workflow_dispatch:
 
jobs:
  regenerate:
    timeout-minutes: 30
    name: Regenerate hex-api cassettes
    runs-on: latchkey-small
    permissions:
      contents: write
      pull-requests: write
 
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Setup Python
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: '3.12'
 
      - name: Install jq (preinstalled on ubuntu-latest but pin explicit)
        run: jq --version
 
      - name: Regenerate cassettes for seed top-100 + smoke fixtures
        id: regen
        run: |
          set -u
          seed_list="plugins/elixir-phoenix/skills/deps-audit/smoke-test/corpus.d/benign-100.txt"
          if [ ! -f "${seed_list}" ]; then
            echo "::error::seed list missing: ${seed_list}"
            exit 1
          fi
 
          updated=0
          while IFS= read -r line; do
            pkg=$(echo "${line}" | awk '{print $1}')
            ver=$(echo "${line}" | awk '{print $2}')
            [ -z "${pkg}" ] && continue
            bash plugins/elixir-phoenix/skills/deps-audit/priv/cassettes/capture.sh \
              "${pkg}" "${ver}" \
              || echo "::warning::capture failed for ${pkg} ${ver}"
            updated=$((updated + 1))
          done < "${seed_list}"
 
          echo "updated_count=${updated}" >> "${GITHUB_OUTPUT}"
 
      - name: Detect cassette drift
        id: drift
        run: |
          # Diff the cassettes dir; empty diff means no PR needed
          if git diff --quiet plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/; then
            echo "drift=false" >> "${GITHUB_OUTPUT}"
            echo "No cassette drift this run."
          else
            echo "drift=true" >> "${GITHUB_OUTPUT}"
            git diff --stat plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/
          fi
 
      - name: Open PR (primary path)
        id: open_pr
        if: steps.drift.outputs.drift == 'true'
        continue-on-error: true
        uses: peter-evans/create-pull-request@v8
        with:
          commit-message: 'chore(cassettes): monthly hex-api regen'
          title: 'Monthly hex-api cassette regeneration'
          body: |
            Auto-generated PR refreshing VCR cassettes from `hex.pm/api`.
 
            **Review checklist:**
            - [ ] Diff per-cassette body for owner/release changes
            - [ ] `_meta.json` SHA entries updated for changed cassettes
            - [ ] No new package's owners list looks suspicious
            - [ ] `captured_at` matches today's date
          branch: chore/hex-api-cassette-regen
          labels: |
            cassette-regen
            security
            auto-pr
 
      - name: 403 fallback - upload as artifact
        if: steps.drift.outputs.drift == 'true' && steps.open_pr.outcome == 'failure'
        uses: actions/upload-artifact@v7
        with:
          name: cassettes-regen-${{ github.run_id }}
          path: plugins/elixir-phoenix/skills/deps-audit/test-assets/hex-api-cassettes/
          retention-days: 90
 
      - name: Job summary
        if: always()
        run: |
          {
            echo "## Cassette regeneration summary"
            echo
            echo "- Packages processed: ${{ steps.regen.outputs.updated_count }}"
            echo "- Drift detected: ${{ steps.drift.outputs.drift }}"
            if [ "${{ steps.drift.outputs.drift }}" = "true" ] && [ "${{ steps.open_pr.outcome }}" = "failure" ]; then
              echo "- **PR creation FAILED (likely 403).** Cassettes uploaded as"
              echo "  artifact \`cassettes-regen-${{ github.run_id }}\`."
              echo "- To enable PR creation: Settings → Actions → Allow GitHub"
              echo "  Actions to create and approve pull requests."
            elif [ "${{ steps.drift.outputs.drift }}" = "true" ]; then
              echo "- PR opened: chore/hex-api-cassette-regen"
            else
              echo "- No drift; no PR needed."
            fi
          } >> "${GITHUB_STEP_SUMMARY}"
 

What changed

1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow