Skip to main content

Performing Hand Seals...

SCROLLS ▸ HOKAGE - GITHUB ACTIONS CI
09

Hokage - GitHub Actions CI

The Capstone → Level H1

You learn by doing, not reading. You now write real tests: locators, page objects, fixtures, a logged-in session, parametrized data, API checks, mocks, and the hostile-DOM corners. The last step is to stop running them by hand. Continuous Integration (CI) runs your whole suite on a fresh cloud machine on every push, so a broken test is caught in minutes, not in production. You hand GitHub one recipe file and read green or red in the Actions tab. No new Python, no new test code - just the workflow file, where it lives, and how to read a run. This is the one rank you finish on GitHub, not in the dojo page: the payoff is a green check on your own repo.

RUN THIS ON GITHUB, NOT LOCALLY

Every other rank ended with a local pytest run and 1 passed. This one does not. GitHub Actions runs in the cloud, so there is no in-browser or local pass to see here. You confirm this rank by pushing your repo and watching the Actions tab. The self-eval tick at the bottom is that honest attestation, not a local pass.

H1

Run your suite in the cloud with GitHub Actions

One concept: a GitHub Actions workflow runs your existing suite on a fresh Linux box on every push and pull request. One skill: reading the workflow file, putting it in the one folder GitHub scans, and reading the Actions result.

CI is a recipe GitHub follows automatically. When you make your repo from the ichiramen-dojo-py template, the workflow already ships inside it - you do not write it from scratch. The instant you push, GitHub spins up a clean Linux machine, installs Python and the browsers, runs pytest, and shows a green check or a red X in the repo's Actions tab. Nothing new to test; you are just teaching a server to run what you already run. Two things decide whether it runs at all: the file must live in exactly .github/workflows/, and its steps must run in order on a machine that starts empty.

Where the recipe lives. GitHub Actions looks in one exact place: .github/workflows/. Any .yml or .yaml file there is a workflow. The folder name and path matter - GitHub does not scan anywhere else.

the one folder GitHub scans - read only
ichiramen-dojo-py/
  .github/
    workflows/
      tests.yml        <- GitHub reads this
  requirements.txt
  pytest.ini
  conftest.py
  tests/
PREDICT - H1

You click Use this template to make your own copy of the repo. Do you have to write the CI workflow from scratch before anything runs?

PREDICT - H2

You put the workflow at ci/tests.yml in the repo root instead of .github/workflows/tests.yml. You push. What happens?

The whole workflow, read top to bottom. This is the file that ships in the template at .github/workflows/tests.yml. You do not edit it to get your first run - read it so you understand what CI does on every push.

.github/workflows/tests.yml - read only
name: IchiRamen Dojo Tests
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: Install Playwright browsers
        run: python -m playwright install --with-deps chromium
      - name: Run tests
        run: pytest --tracing=retain-on-failure
      - name: Upload traces
        uses: actions/upload-artifact@v7
        if: ${{ !cancelled() }}
        with:
          name: playwright-traces
          path: test-results/

The five steps, plainly: actions/checkout@v7 copies your repo onto the empty machine; actions/setup-python@v6 installs Python (quote '3.12' so YAML does not read it as a number and drop a trailing zero on something like 3.10); pip install -r requirements.txt installs the same deps you use locally; python -m playwright install --with-deps chromium downloads the browser plus the system libraries it needs to launch on bare CI Linux; pytest --tracing=retain-on-failure runs the suite and keeps a trace for any failure; the upload step ships those traces as an artifact you can download.

Harmless YAML aside. YAML's older spec treats some bare words as booleans - the "Norway problem," where no/yes/on/off parse as False/True. If you ever load this file with Python's yaml.safe_load, the top-level key on: comes back as the boolean True, not the string "on". That is a quirk of that one Python parser; GitHub uses its own workflow parser and reads on: correctly, so your CI is unaffected. Mentioned only so a Python self-check does not throw you.

Four mistakes this rank inoculates you against. The wrong path (ci/tests.yml instead of .github/workflows/tests.yml) is the first - that is beat H2 above, and the file-tree shows the right place. The other three are one-line workflow slips:

✗ artifact name has a slash
      - uses: actions/upload-artifact@v7
        with:
          name: playwright/traces
          path: test-results/
✓ flat name, no slash
      - uses: actions/upload-artifact@v7
        with:
          name: playwright-traces
          path: test-results/

Artifact names cannot contain / - a slash is rejected and the upload fails.

✗ upload skipped when tests fail
      - name: Run tests
        run: pytest --tracing=retain-on-failure
      - uses: actions/upload-artifact@v7
        with:
          name: playwright-traces
          path: test-results/
✓ upload runs even on failure
      - name: Run tests
        run: pytest --tracing=retain-on-failure
      - uses: actions/upload-artifact@v7
        if: ${{ !cancelled() }}
        with:
          name: playwright-traces
          path: test-results/

Without if: ${{ !cancelled() }}, a failed test step stops the job and the upload never runs - so the trace of the failure you actually need is never saved. The !cancelled() condition means "run this unless I manually cancelled the whole thing," so traces upload on pass AND on failure.

✗ browsers without system libs
      - run: python -m playwright install chromium
✓ with system deps
      - run: python -m playwright install --with-deps chromium

On a bare CI Linux box Chromium cannot launch without its system libraries. --with-deps installs them; leave it off locally (your machine already has them), keep it on in CI.

There is no local pytest to fix here - this rank happens on GitHub. Do this on your own copy of the template repo:

.github/workflows/tests.yml

1. Confirm the workflow above exists at .github/workflows/tests.yml in your repo (the template ships it). 2. Push any commit to main, or open a pull request. 3. Open your repo's Actions tab and watch the run: a green check means the whole suite passed on a clean machine; a red X means a test failed. 4. If it is red, open the run, download the playwright-traces artifact, unzip it, and open a trace:

playwright show-trace path/to/trace.zip

That opens the same trace viewer you use locally - a timeline, a DOM snapshot per action, the network calls, and the exact step that failed. A CI failure is no longer a mystery log; it is a trace you can scrub, because retain-on-failure saved it and the upload step shipped it.

OPTIONAL UPGRADE - HERMETIC CI (read only)

The workflow above runs with no --base-url, so it uses the pytest.ini default and reaches the LIVE site over the network every run. Simple to teach, but it makes a green badge depend on the live deploy. Because IchiRamen is a static site, a stronger CI checks out the app repo (tebrex1995/portfolio-aleksa) too, serves its src/ on a local port in the background, and points the suite at it with --base-url http://localhost:8099 - fully offline and deterministic. Recommended for a public portfolio repo whose green badge is the whole point; the simple version above is the clearer thing to learn first.

One term to know: sharding splits a large suite across several parallel machines to finish faster. You do not need it for a suite this size - just recognize the word when a bigger project reaches for it.

Honest limit of this rank: the workflow is validated against documented GitHub Actions behavior and parses as valid YAML, but it is not executed end to end inside the dojo - it runs on your GitHub, not in this page.

← ANBU - Hostile DOM You have walked the whole path. Return to the Ninja Path →