Skip to content
Draft
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
302 changes: 145 additions & 157 deletions .github/plugin/marketplace.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ jobs:
- name: Install dependencies
run: npm ci

# Installs the APM CLI (latest stable) and adds `apm` to PATH for
# subsequent steps. `npm run build` invokes `apm pack` to build
# .github/plugin/marketplace.json from apm.yml; the CLI must be
# available on the runner. Mirrors the pattern microsoft/apm uses
# in its own CI (see microsoft/apm/.github/workflows/ci.yml).
- uses: microsoft/apm-action@v1

- name: Materialize plugin files
run: node eng/materialize-plugins.mjs

Expand Down
116 changes: 116 additions & 0 deletions .github/workflows/validate-marketplace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Validate Marketplace

# Runs on PRs that touch any input to the marketplace.json build chain
# (apm.yml, plugin manifests, external plugin registry, the bridge merge
# script, or the legacy generator). Two gates, both wired through the
# canonical APM consumer pattern shipped by microsoft/apm-action@v1
# (the same install+audit substrate used by downstream consumers such
# as DevExpGbb/zava-agent-config, whose reusable apm-audit.yml is the
# golden example for repos with a real `dependencies:` block):
#
# Gate A (supply-chain): `apm audit --ci`. Validates lockfile / install
# fidelity, ref consistency between apm.yml and apm.lock.yaml,
# no orphan packages, and content-integrity (hidden Unicode) on
# deployed package content. Short-circuits cleanly on this repo today
# (no `dependencies:` block -- marketplace-only manifest), but fires
# automatically the moment awesome-copilot adds a real dependency.
# SARIF report is uploaded to the run when apm-action produces one.
#
# Gate B (drift): rebuild marketplace.json with `apm pack` + the
# external-plugin merge bridge, and fail if the result differs from
# the committed `.github/plugin/marketplace.json`. Catches contributors
# who edit apm.yml without re-running `npm run build`, or who
# hand-edit the generated marketplace.json. This is the producer-side
# counterpart to the consumer-side gate (`apm marketplace check`)
# documented in microsoft/apm's producer guide -- we cannot use
# `apm marketplace check` directly today because it does not yet
# short-circuit local-path sources (treats `./plugins/<name>` as
# remote refs).

on:
pull_request:
branches: [staged, main]
paths:
- "apm.yml"
- "apm.lock.yaml"
- "plugins/**/.github/plugin/plugin.json"
- "plugins/external.json"
- "eng/merge-external-plugins.mjs"
- "eng/generate-marketplace.mjs"
- ".github/plugin/marketplace.json"
- ".github/workflows/validate-marketplace.yml"

permissions:
contents: read
security-events: write

jobs:
audit-and-drift:
name: APM audit + marketplace drift
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Extract Node version from package.json
id: node-version
run: |
NODE_VERSION=$(jq -r '.engines.node // "22"' package.json)
echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT"

- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ steps.node-version.outputs.version }}

- name: Install Node dependencies
run: npm ci

# Installs the APM CLI (latest stable), runs `apm install` against
# this repo's apm.yml, and emits a SARIF audit report consumed by
# the upload step below. For a marketplace-only manifest with no
# `dependencies:` block, install is effectively a no-op; the value
# this step adds is making `apm` available on PATH and producing
# the SARIF artifact.
- name: Setup APM
uses: microsoft/apm-action@v1
with:
audit-report: 'true'

# Gate A: supply-chain integrity (consumer-side).
# `apm audit --ci` exits non-zero on policy failures (lockfile drift,
# orphan packages, hidden Unicode in deployed content). On a
# marketplace-only manifest with no `dependencies:` block this is a
# short-circuit pass ("No dependencies declared -- lockfile not
# required"), but the gate is wired so the moment awesome-copilot
# adds a real dependency the policy fires automatically.
- name: apm audit --ci
run: apm audit --ci

# SARIF upload only runs when apm-action actually produced a report.
# For marketplace-only manifests there is no lockfile to scan, so
# apm-action emits "No apm.lock.yaml found -- nothing to scan" and
# writes no file. Guarding on hashFiles() avoids a spurious failure.
- name: Upload APM audit SARIF
if: always() && hashFiles('apm-audit.sarif') != ''
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: apm-audit.sarif
category: apm-audit

# Gate B: marketplace.json drift (producer-side).
# `npm run build` now invokes `apm pack` + the external-plugin merge
# bridge. If the rebuild produces a different marketplace.json than
# the one committed in this PR, fail with a clear remediation hint.
- name: Rebuild marketplace.json
run: npm run build

- name: Check marketplace.json drift
run: |
if [ -n "$(git status --porcelain -- .github/plugin/marketplace.json)" ]; then
echo "::error::.github/plugin/marketplace.json is out of sync with apm.yml + plugins/external.json."
echo "Run 'npm run build' locally and commit the regenerated marketplace.json."
git --no-pager diff -- .github/plugin/marketplace.json
exit 1
fi
echo "marketplace.json is in sync."
17 changes: 16 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ To maintain a safe, responsible, and high-signal collection, we will **not accep

## How to Contribute

### Prerequisites

This repository uses [APM (Agent Package Manager)](https://github.com/microsoft/apm) to author the marketplace manifest. Install the `apm` CLI before running `npm run build` (it is invoked from the build chain to generate `.github/plugin/marketplace.json`):

```bash
curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh
```

Then install Node dependencies as usual:

```bash
npm install
```

### Adding Instructions

Instructions help customize GitHub Copilot's behavior for specific technologies, coding practices, or domains.
Expand Down Expand Up @@ -144,7 +158,8 @@ Plugins group related agents, commands, and skills around specific themes or wor
1. **Create your plugin**: Run `npm run plugin:create` to scaffold a new plugin
2. **Follow the naming convention**: Use descriptive, lowercase folder names with hyphens (e.g., `python-web-development`)
3. **Define your content**: List agents, commands, and skills in `plugin.json` using the Claude Code spec fields
4. **Test your plugin**: Run `npm run plugin:validate` to verify your plugin structure
4. **Register in `apm.yml`**: Append a `packages:` entry under `marketplace:` (alphabetical) with `source: ./plugins/<name>`, `version`, and `description` matching your plugin.json. This is what `apm pack` reads to assemble the marketplace.
5. **Test your plugin**: Run `npm run plugin:validate` to verify your plugin structure

#### Creating a plugin

Expand Down
Loading
Loading