Skip to content

ci: validate SKILL.md frontmatter on pull requests - #202

Merged
devin-ai-integration[bot] merged 3 commits into
mainfrom
devin/1793121495-validate-skill-frontmatter
Oct 27, 2026
Merged

devin-ai-integration[bot] merged 3 commits into
mainfrom
devin/1793121495-validate-skill-frontmatter

Conversation

@mattapperson

@mattapperson mattapperson commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds .github/workflows/validate-skills.yml. It runs gh skill publish --dry-run . on every PR and on every push to main. This is the first CI in the repo.

Why: #192 merged a description with an unquoted : . After that, gh skill install OpenRouterTeam/skills openrouter-decisions failed with invalid frontmatter YAML: yaml: line 2: mapping values are not allowed in this context. publish --dry-run uses the same frontmatter parser as install, plus the agentskills.io checks: name and description are present, and name matches the directory. So the check fails on exactly the errors users hit at install time. Warnings such as a missing license or a long body don't fail it.

  • The gh CLI is pinned to 2.103.3 and downloaded from the cli/cli release, because gh skill is a preview command and may not exist on the runner's gh.
  • No token is needed. I ran the dry run locally with no gh auth and it passed.

Verified:

What still doesn't work

Searched existing PRs: #193 adds the third-party LintLang linter. I ran its exact command (lintlang scan --discover . --fail-on fail, 0.8.1) on the broken main, and it passed all 19 SKILL.md files, including openrouter-decisions, so it doesn't catch this class of error. This PR doesn't supersede #193.

Link to Devin session: https://openrouter.devinenterprise.com/sessions/485ff7dc41114055a8d0407a0b3f7911
Open in Devin Desktop: https://openrouter.devinenterprise.com/desktop/session/485ff7dc41114055a8d0407a0b3f7911?variant=devin
Requested by: @mattapperson


Devin Review

@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access that start with 'Devin'.

  • Disable automatic comment, CI, and merge conflict monitoring

Original prompt from Matt

SYSTEM:
<latest_message>
Matt Apperson (U096UCX4GDS) [ts=1793121284.635609]: @Devin installing skills from our skills repo is resulting in an error of "failed to install skill "openrouter-decisions": could not inject metadata: invalid frontmatter YAML: yaml: line 2: mapping values are not allowed in this context" look into this
</latest_message>

=== BEGIN THREAD HISTORY (in #eng-devex-team) ===
Matt Apperson (U096UCX4GDS) [ts=1793121284.635609]: @Devin installing skills from our skills repo is resulting in an error of "failed to install skill "openrouter-decisions": could not inject metadata: invalid frontmatter YAML: yaml: line 2: mapping values are not allowed in this context" look into this
=== END THREAD HISTORY ===
Channel ID: C0BCDN7RHJM
Thread URL: https://openrouter.slack.com/archives/C0BCDN7RHJM/p1793121284635609?thread_ts=1793121284.635609&amp;cid=C0BCDN7RHJM

The <latest_message> is the message that you should use to guide your goals + task for this session, and you should use the rest of the slack thread as context.
A [ts=...] marker on a Slack message is that message's timestamp. To act on a specific message with the slack tool (e.g. adding an emoji reaction via the reaction command), pass that value as timestamp along with the Channel ID — no extra lookup call is needed.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

perry-the-pr-reviewer[bot]

This comment was marked as resolved.

Co-Authored-By: Matt Apperson <me@mattapperson.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Thanks, Perry. I've applied both inline items in 0067915 and already removed the stale #198 caveat from the PR body. Making validate a required status check in the basic ruleset needs repo admin, so I've raised it with the requester rather than changing it here.

@perry-the-pr-maintainer perry-the-pr-maintainer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perry's Review

Verdict: ✅ LGTM

Both findings from my previous review are fixed in 00679152, and I verified the fixes rather than reading them:

  • The actions/checkout step — pinned to 11d5960a326750d5838078e36cf38b85af677262, which is the commit the v4 tag resolves to.
  • The "Install pinned GitHub CLI" step — the tarball is downloaded, its published checksum verified, and only then extracted. I ran the step in a clean RUNNER_TEMP: it installs gh 2.103.3 and exits 0. I then tampered the tarball and re-ran it: FAILED … 1 computed checksum did NOT match, exit 1. I also checked the case where grep matches nothing — sha256sum: 'no properly formatted checksum lines found', exit 1 — so a renamed or missing asset fails closed rather than checking nothing.

The check still does its job on the current head: gh skill publish --dry-run . exits 0 on this tree, and exits 1 with invalid frontmatter YAML: yaml: line 2: mapping values are not allowed in this context when the pre-#198 unquoted description is restored. It also catches a newly added skill with broken YAML, a skill with no frontmatter, and a name/directory mismatch, and it correctly ignores the license/long-body warnings. The stale "will fail until #198 merges" caveat is gone from the description.

One thing this PR does not do, which is worth stating plainly so nobody reads more safety into it than exists: the check is not yet required to merge. The active basic ruleset (14604602) contains only deletion, non_fast_forward, and pull_request rules — there is no required_status_checks rule. A red run here is visible on the PR but does not block the merge, so recurrence is still possible. Adding "Validate skills" under Settings → Rules → basic → required status checks closes it. I am approving the workflow because that is a repository-settings change outside this diff, not a defect in it — but please make that change, or this is a signal rather than a gate.

Risk assessment

Risk: 🟡 Medium

Dimension Severity Risk Reasoning
Implementation risk 🟩 Low Install, checksum, tamper-detection, and the validation step were all executed and behave correctly.
Premise risk 🟨🟨 Medium The check catches the regression, but as merged it reports rather than blocks until it is made required.
Estimated impact 🟨🟨 Medium Worst case a broken skill frontmatter ships again and users hit the same install error.
Risk Factor Severity Risk Reasoning
Reversibility 🟩 Low A workflow file reverts cleanly.
Detectability 🟩 Low The failure is printed on every affected PR.
Blast radius 🟩 Low Repo CI only; no runtime surface.
Data integrity None No persisted state.
Financial exposure None No billing surface.
Security and privacy exposure 🟩 Low Download is now checksum-verified and the action is commit-pinned.
Propagation 🟨🟨 Medium A bad skill still reaches users via gh skill install and the plugin marketplace if merged past a red run.
Availability 🟩 Low A failed download fails one job, not a product path.
Recovery cost 🟩 Low One-line quoting fix, as #198 showed.
Time to correct 🟩 Low Immediate once noticed.

Estimated impact: Worst case is a repeat of #192 — malformed skill frontmatter reaches main and every user installing that skill gets an error that looks like a CLI fault rather than a repo defect.

@devin-ai-integration
devin-ai-integration Bot merged commit 76e2072 into main Oct 27, 2026
2 checks passed
@devin-ai-integration
devin-ai-integration Bot deleted the devin/1793121495-validate-skill-frontmatter branch October 27, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant