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
79 changes: 75 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -199,22 +199,87 @@ jobs:
if: always()
run: thv stop --all || true

test-skill-build-action:
name: Test Skill Build Action
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install ToolHive
uses: ./install

- name: Create Test Skill
run: |
mkdir -p test-skill
cat > test-skill/SKILL.md << 'SKILLEOF'
---
name: test-skill
description: "A test skill for CI validation"
version: "0.1.0"
license: Apache-2.0
---

# Test Skill

This is a test skill used to validate the skill-build action.
SKILLEOF

- name: Test Build Action (default tag)
id: build
uses: ./skill-build
with:
path: ./test-skill

- name: Verify Build Output
env:
REFERENCE: ${{ steps.build.outputs.reference }}
run: |
echo "Built reference: $REFERENCE"

if [ -z "$REFERENCE" ]; then
echo "Error: No reference output from build"
exit 1
fi

echo "Skill build test passed"

- name: Test Build Action (custom tag)
id: build-tagged
uses: ./skill-build
with:
path: ./test-skill
tag: test-skill:ci

- name: Verify Tagged Build Output
env:
REFERENCE: ${{ steps.build-tagged.outputs.reference }}
run: |
echo "Built reference: $REFERENCE"

if [ -z "$REFERENCE" ]; then
echo "Error: No reference output from tagged build"
exit 1
fi

echo "Tagged skill build test passed"

validate-action-metadata:
name: Validate Action Metadata
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup yq
uses: mikefarah/yq@v4

- name: Validate install/action.yml
run: |
echo "Validating install/action.yml..."
yq eval '.' install/action.yml > /dev/null
echo "✓ install/action.yml is valid"

- name: Validate run-mcp-server/action.yml
run: |
echo "Validating run-mcp-server/action.yml..."
Expand All @@ -225,4 +290,10 @@ jobs:
run: |
echo "Validating mcp-config/action.yml..."
yq eval '.' mcp-config/action.yml > /dev/null
echo "✓ mcp-config/action.yml is valid"
echo "✓ mcp-config/action.yml is valid"

- name: Validate skill-build/action.yml
run: |
echo "Validating skill-build/action.yml..."
yq eval '.' skill-build/action.yml > /dev/null
echo "✓ skill-build/action.yml is valid"
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ Persists MCP server configurations to a file and optionally uploads as an artifa

[📖 Full Documentation](./mcp-config/README.md)

### 4. `skill-build` - Build ToolHive Skills

Build and optionally push a ToolHive skill as an OCI artifact.

**Features:**
- 🏗️ Build skills from a local directory containing `SKILL.md`
- 🏷️ Custom OCI tagging
- 📤 Push to any OCI-compatible registry (ghcr.io, Docker Hub, etc.)
- ✅ Validates skill structure before building

[📖 Full Documentation](./skill-build/README.md)

## 📚 Examples

### Basic Installation and Usage
Expand Down
164 changes: 164 additions & 0 deletions skill-build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Build ToolHive Skill Action

Build and optionally push a [ToolHive](https://github.com/stacklok/toolhive) skill as an OCI artifact. Skills are portable knowledge packages for AI agents following the [Agent Skills Specification](https://agentskills.io/specification).

## Features

- Build a skill from a local directory containing a `SKILL.md`
- Tag the resulting OCI artifact with a custom reference
- Optionally push to any OCI-compatible registry (ghcr.io, Docker Hub, etc.)
- Validates skill structure before building

## Prerequisites

- ToolHive CLI must be installed (use the [install action](../install/README.md))
- For pushing: registry credentials must be configured before this action runs (e.g., via [docker/login-action](https://github.com/docker/login-action))

## Inputs

| Input | Description | Required | Default |
|-------|-------------|----------|---------|
| `path` | Path to the skill directory containing `SKILL.md` | Yes | - |
| `tag` | OCI tag for the built artifact (e.g., `ghcr.io/org/skill-name:v1.0.0`) | No | Skill name from `SKILL.md` |
| `push` | Push the artifact to a remote OCI registry | No | `false` |

## Outputs

| Output | Description |
|--------|-------------|
| `reference` | OCI reference of the built skill artifact |

## Usage

### Build Only

```yaml
steps:
- uses: actions/checkout@v4

- uses: stacklok/toolhive-actions/install@v0

- name: Build skill
id: build
uses: stacklok/toolhive-actions/skill-build@v0
with:
path: ./my-skill
```

### Build and Push to GHCR

```yaml
steps:
- uses: actions/checkout@v4

- uses: stacklok/toolhive-actions/install@v0

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push skill
id: build
uses: stacklok/toolhive-actions/skill-build@v0
with:
path: ./my-skill
tag: ghcr.io/${{ github.repository_owner }}/my-skill:latest
push: 'true'
```

### Build and Push with Semantic Versioning

```yaml
steps:
- uses: actions/checkout@v4

- uses: stacklok/toolhive-actions/install@v0

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push skill
uses: stacklok/toolhive-actions/skill-build@v0
with:
path: ./skills/my-skill
tag: ghcr.io/${{ github.repository_owner }}/my-skill:${{ github.ref_name }}
push: 'true'
```

## Skill Directory Structure

A skill directory must contain at minimum a `SKILL.md` file with YAML frontmatter:

```
my-skill/
SKILL.md # Required: skill definition with frontmatter
references/ # Optional: additional documentation
COMMANDS.md
EXAMPLES.md
```

Example `SKILL.md`:

```markdown
---
name: my-skill
description: "A brief description of what this skill does"
version: "0.1.0"
license: Apache-2.0
---

# My Skill

Detailed documentation and instructions for the AI agent...
```

See the [Agent Skills Specification](https://agentskills.io/specification) for the full format.

## Platform Support

| Platform | Status |
|----------|--------|
| Ubuntu (Linux) | Supported |
| macOS | Supported |
| Windows | Not yet tested |

## Security

- The action validates the skill directory structure before building
- No registry credentials are handled by this action — use a dedicated login action (e.g., `docker/login-action`) to configure credentials before pushing
- The ToolHive daemon is started on a random available port and stopped after the action completes

## Troubleshooting

### "ToolHive CLI (thv) is not installed"

Add the install action before this action:

```yaml
- uses: stacklok/toolhive-actions/install@v0
```

### "SKILL.md not found"

Ensure your `path` input points to a directory containing a valid `SKILL.md` file.

### "ToolHive daemon failed to start"

Check that the ToolHive version you installed supports the `skill` command. This feature requires a recent version of ToolHive.

### Push fails with authentication error

Ensure you have logged in to your registry before running this action. For example:

```yaml
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
```
Loading
Loading