Skip to content
Merged
Show file tree
Hide file tree
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
59 changes: 40 additions & 19 deletions .github/workflows/reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: reusable
#
# jobs:
# evals:
# uses: amd/skillscope/.github/workflows/reusable.yml@main
# uses: amd/skillscope/.github/workflows/reusable.yml@v0.1.1
# secrets:
# api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# with:
Expand Down Expand Up @@ -58,6 +58,13 @@ name: reusable
# your provider, your gateway, or anything else in the vault. `secrets: inherit`
# still works if you would rather pass the vault and name the key with
# `api_key_secret`; it is more than this workflow needs.
#
# The `uses:` pin on this workflow is the harness that runs. GitHub does not
# let a reusable workflow interpolate that pin into `uses: amd/skillscope@...`,
# so each job checks out this repository at `job.workflow_sha` (the commit the
# caller referenced) and runs the composite action from that tree. Pinning
# `@v0.1.1` grades with v0.1.1, `@main` grades with main, and a branch grades
# with that branch -- so there is no release ritual and nothing to keep in step.

on:
workflow_call:
Expand Down Expand Up @@ -99,12 +106,6 @@ on:
wrong routing decision; `0` reports the score without gating on it.
type: string
default: "1"
version:
description: >-
Harness version to run, overriding the pin in each skill's evals.json.
Blank runs those pins, and this workflow's own ref where there is none.
type: string
default: ""
api_key_secret:
description: >-
Name of the secret holding the model API key when the caller uses
Expand Down Expand Up @@ -144,6 +145,13 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Check out skillscope
uses: actions/checkout@v4
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .skillscope-action

# One glob per line is how a list wants to be written in YAML, and commas
# are what every skillscope flag takes. Accept both, pass on one.
- name: Read the skill list
Expand All @@ -166,11 +174,10 @@ jobs:
# everything else that runs against it.
- name: List the skills
id: found
uses: amd/skillscope@main
uses: ./.skillscope-action
with:
command: list-skills
skills: ${{ steps.globs.outputs.globs }}
version: ${{ inputs.version }}

- name: Build the matrix
id: matrix
Expand Down Expand Up @@ -240,12 +247,18 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Check out skillscope
uses: actions/checkout@v4
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .skillscope-action

- name: Check every skill's structure
uses: amd/skillscope@main
uses: ./.skillscope-action
with:
command: structural
skills: ${{ needs.discover.outputs.globs }}
version: ${{ inputs.version }}

routing:
name: Routing Tests (${{ matrix.skill }})
Expand All @@ -272,6 +285,13 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Check out skillscope
uses: actions/checkout@v4
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .skillscope-action

- name: Check the model credentials
shell: bash
env:
Expand All @@ -290,7 +310,7 @@ jobs:
fi

- name: Run the routing eval for ${{ matrix.skill }}
uses: amd/skillscope@main
uses: ./.skillscope-action
with:
command: routing
# One skill in the room, named, so the score is about this skill alone
Expand All @@ -303,8 +323,6 @@ jobs:
--output routing-report.json
--keep-logs routing-logs
skills: ${{ needs.discover.outputs.globs }}
skill: ${{ matrix.skill }}
version: ${{ inputs.version }}
install-claude: "true"

- name: Upload the routing report
Expand Down Expand Up @@ -338,6 +356,13 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Check out skillscope
uses: actions/checkout@v4
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .skillscope-action

- name: Check the model credentials
shell: bash
env:
Expand All @@ -356,17 +381,13 @@ jobs:
fi

- name: Run the behavioral cases for ${{ matrix.skill }}
uses: amd/skillscope@main
uses: ./.skillscope-action
with:
command: behavioral
args: >-
--skill '${{ matrix.skill }}'
--output behavioral-report.json
skills: ${{ needs.discover.outputs.globs }}
# This skill's own evals.json may pin the harness version its cases
# were written for, and this is the leg that runs them.
skill: ${{ matrix.skill }}
version: ${{ inputs.version }}
install-claude: "true"

- name: Upload the behavioral report
Expand Down
40 changes: 26 additions & 14 deletions .github/workflows/selftest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ name: selftest
# Two halves. The unit suite guards the parts that decide whether a paid run is
# trustworthy -- routing verdicts, activation detection, dataset rejection --
# and runs on every platform a behavioral leg can be scheduled on, because that
# is where the path handling breaks. The smoke test drives the real launcher
# is where the path handling breaks. The smoke test drives the real action
# against a throwaway repo built in the job, which is the only way to find out
# that action.yml, the version resolver, and the CLI still agree on their
# interface.
# that action.yml and the CLI still agree on their interface.

on:
push:
Expand Down Expand Up @@ -45,8 +44,8 @@ jobs:
- name: Run the suite
run: python -m unittest discover -s tests -t . --verbose

launcher:
name: Launcher against a throwaway repo
action:
name: Action against a throwaway repo
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -92,19 +91,36 @@ jobs:
}
EOF

# `source: .` installs this checkout rather than a published ref, so a
# pull request tests the launcher and the payload it is about to change.
# No `version`: the fixture pins nothing, which exercises the bottom rung
# of the resolution ladder.
# `uses: ./` runs this checkout, so a pull request tests the action and
# the harness it is about to change.
- name: Check the fixture structurally
id: structural
uses: ./
with:
command: structural
# The card and its sections are a repo's own policy, so the fixture
# asks for them the way a repo with a governance card would.
args: --skill-files skill-card.md --skill-sections Description,Owner,License
repo: fixture
source: .

# The version story, end to end. Nothing here can fetch another build, so
# the harness that just ran has to be the one in this checkout -- and the
# action has to be able to say which one that was. It reports the version
# rather than its own ref precisely because the reusable workflows reach
# it through a nested checkout, where the ref is empty.
- name: Check it ran the harness from this checkout
shell: python
env:
REPORTED: ${{ steps.structural.outputs.version }}
run: |
import os
import re

pyproject = open("pyproject.toml", encoding="utf-8").read()
declared = re.search(r'(?m)^version\s*=\s*"([^"]+)"', pyproject).group(1)
reported = os.environ["REPORTED"]
assert reported == declared, f"ran {reported!r}, but this checkout is {declared!r}"
print(f"skillscope {reported}, from this checkout.")

# This repo has no skills, so what is left is its own prose -- which is
# exactly the half a harness for checking references should not be
Expand All @@ -116,7 +132,6 @@ jobs:
with:
command: structural
args: --docs '*.md,docs/**/*.md'
source: .

- name: Select runs for a change
id: select
Expand All @@ -125,7 +140,6 @@ jobs:
command: select
args: --all --routing-room demo-skill
repo: fixture
source: .

- name: Select runs without naming the routing set
id: inferred
Expand All @@ -134,7 +148,6 @@ jobs:
command: select
args: --all
repo: fixture
source: .

- name: Select runs with routing turned off
id: unrouted
Expand All @@ -143,7 +156,6 @@ jobs:
command: select
args: --all --routing-room none
repo: fixture
source: .

- name: Check the plan
shell: python
Expand Down
Loading
Loading