Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Github Composite Actions

ASecurity

Use when writing, debugging, or designing GitHub Actions composite actions. Covers the `uses:` field rules, relative path resolution, composite-to-composite calling, secrets limitations, differences from reusable workflows, and best practices.

8 stars
0 votes
0 copies
0 views
Added 9/20/2026
devopsshellbashexpressdebugginggitsecurity

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add tstapler/dotfiles --skill github-composite-actions --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Github Composite Actions?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Github Composite Actions
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tstapler-github-composite-actions/badge)](https://www.skillsdirectory.com/skills/tstapler-github-composite-actions)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: github-composite-actions
description: Use when writing, debugging, or designing GitHub Actions composite actions. Covers the `uses:` field rules, relative path resolution, composite-to-composite calling, secrets limitations, differences from reusable workflows, and best practices.
---

# GitHub Actions Composite Actions

Reference for writing and debugging composite actions (`action.yml` files with `runs.using: composite`).

> For debugging failures in composite action runs, apply the `github-actions-debugging` skill.

## Critical Limitations (Know Before You Code)

### `uses:` Does NOT Support Expressions

The `uses:` field is evaluated at parse time — expressions like `${{ inputs.ref }}` or `${{ env.VERSION }}` will **not** be evaluated. All references must be literal strings.

```yaml
# WRONG — will not work
uses: my-org/actions/my-action@${{ inputs.version }}

# CORRECT — must be a literal ref
uses: my-org/actions/my-action@v2
uses: my-org/actions/my-action@abc1234
uses: my-org/actions/my-action@main
```

**Confirmed by:** [GitHub community discussion #44832](https://github.com/orgs/community/discussions/44832), GitHub staff, and official docs:
> "You cannot use contexts or expressions in this keyword."

**Workaround:** Pass the ref value as an `input` to the action, and have the action use it inside a `run:` step or pass it to a nested checkout.

### Secrets Context Is Blocked

Composite actions cannot access `${{ secrets.MY_SECRET }}` directly. The `secrets` context is unavailable.

```yaml
# WRONG — secrets context unavailable
- run: echo ${{ secrets.MY_TOKEN }}

# CORRECT — require caller to pass secrets as inputs
inputs:
  github-token:
    required: true
steps:
  - run: echo ${{ inputs.github-token }}
```

Secrets passed as inputs **are masked in logs** by the runner.

Sources: [actions/runner issue #1284](https://github.com/actions/runner/issues/1284), [docs issue #12705](https://github.com/github/docs/issues/12705)

### `GITHUB_ENV` Does Not Propagate to Caller

Environment variables set via `$GITHUB_ENV` inside a composite action stay within the composite — they do **not** flow back to the calling workflow's subsequent steps.

### No Top-Level `env:` Block

There is no job-level `env:` block in `action.yml`. Set env vars at the step level only:

```yaml
steps:
  - name: My step
    shell: bash
    env:
      MY_VAR: ${{ inputs.my-input }}
    run: echo "$MY_VAR"
```

---

## Relative Path Resolution

Relative paths in composite action `uses:` resolve to **`$GITHUB_WORKSPACE`**, not to the current action's directory.

```yaml
# In .github/actions/my-action/action.yml:
steps:
  - uses: ./other-action
  # Resolves to: $GITHUB_WORKSPACE/other-action  (NOT .github/actions/other-action)
```

This is a known pain point for monorepos. Tracked: [actions/runner issue #2101](https://github.com/actions/runner/issues/2101).

**Pattern to work around this:** Check out the actions repo explicitly, then reference by path:

```yaml
- uses: actions/checkout@v4
  with:
    repository: my-org/actions
    ref: v1
    path: actions-repo
    token: ${{ inputs.github-token }}

- uses: ./actions-repo/path/to/sibling-action
```

**Use `github.action_path` for scripts/files relative to the action itself:**

```yaml
- shell: bash
  run: ${{ github.action_path }}/scripts/my-script.sh
```

---

## Composite Calling Composite

Composite actions support nesting up to **10 levels deep**. If the limit is exceeded, the job fails during "Set up job."

Each level receives only what is explicitly passed via `with:` — no implicit context or env inheritance.

```yaml
# Outer composite: my-org/actions/build/action.yml
steps:
  - uses: my-org/actions/build/report-error@v1   # literal ref required
    with:
      github-token: ${{ inputs.github-token }}   # must explicitly re-pass
      build-tool: GRADLE
```

Reusable workflows, by contrast, **cannot** call other reusable workflows (one level only).

---

## Composite vs. Reusable Workflow — When to Use Which

| Need | Use |
|------|-----|
| Reusable steps within a single job | Composite action |
| Multiple jobs with different runners | Reusable workflow |
| `secrets: inherit` | Reusable workflow |
| Deployment environments | Reusable workflow |
| Matrix strategy | Reusable workflow |
| Caller can add steps before/after | Composite action |
| Steps need to run on same runner as caller | Composite action |

**Full limitation comparison (composite actions lack these vs. workflows):**

- Multiple jobs / `needs:` dependency graph
- `runs-on:` per-job runner selection
- `secrets:` context (must pass as inputs)
- Job-level `env:` block
- Job-level `if:` / `continue-on-error:` / `timeout-minutes:`
- `environment:` (deployment environments)
- `concurrency:` groups
- Matrix strategy

---

## Best Practices

### Always Use `github.action_path` for Internal Files

```yaml
- shell: bash
  run: ${{ github.action_path }}/scripts/setup.sh
```

### Pin External Actions to a SHA or Tag

```yaml
- uses: actions/checkout@v4          # tag — readable
- uses: actions/checkout@abc1234     # SHA — more secure
# Never: uses: actions/checkout@main  (in production)
```

### Explicit Input-to-Env Mapping

Composite actions do NOT auto-expose inputs as env vars. Map them explicitly:

```yaml
steps:
  - name: Run build
    shell: bash
    env:
      BUILD_TOOL: ${{ inputs.build-tool }}
      OUTPUT_FILE: ${{ inputs.output-file }}
    run: ./build.sh
```

### Descriptive Step Names

All steps are collapsed under the parent step in the GitHub UI. Add clear names so the collapsed view is readable.

### `continue-on-error: true` on Optional Steps

For observability or reporting steps that should never block the primary outcome:

```yaml
- name: Report errors
  if: always() && steps.build.outputs.build_failed == 'true'
  continue-on-error: true
  uses: my-org/actions/report-error@v1
  with:
    github-token: ${{ github.token }}
```

### Deferred Exit Code Pattern

When you need artifacts/reporting to run even after a build failure, capture the exit code instead of failing immediately:

```yaml
- name: Build
  id: build
  shell: bash {0}          # disables errexit for this step
  run: |
    ./gradlew build
    echo "exit_code=$?" >> $GITHUB_OUTPUT
    echo "build_failed=$([[ $? -ne 0 ]] && echo true || echo false)" >> $GITHUB_OUTPUT

- name: Upload logs
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: build-logs
    path: /tmp/build-output.txt

- name: Exit with real status
  shell: bash
  run: exit $(cat /tmp/build-exit-code.txt)
```

---

## Sources

- [GitHub Docs: Creating a composite action](https://docs.github.com/actions/creating-actions/creating-a-composite-action)
- [GitHub Docs: Metadata syntax reference](https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax)
- [GitHub Docs: Reuse workflows](https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows)
- [Community #44832: `uses` does not evaluate expressions](https://github.com/orgs/community/discussions/44832)
- [actions/runner #1284: Secrets in composite actions](https://github.com/actions/runner/issues/1284)
- [actions/runner #2101: Monorepo composite action path resolution](https://github.com/actions/runner/issues/2101)
- [actions/runner ADR 1144: Composite actions design (10-level nesting limit)](https://github.com/actions/runner/blob/main/docs/adrs/1144-composite-actions.md)
- [DEV: Composite Actions vs Reusable Workflows](https://dev.to/n3wt0n/composite-actions-vs-reusable-workflows-what-is-the-difference-github-actions-11kd)

---

## Related Skills

| Skill | When to apply |
|-------|--------------|
| `github-actions-debugging` | Debug failures in composite action run logs |
| `github-pr` | Open a PR after authoring or updating an action |
| `security-review` | Review composite action for secret exposure risks |

Attribution

tstaplertstapler
View sourceMore from tstapler →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Terraform Module Library

Build reusable Terraform modules for AWS, Azure, and GCP infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.

393431 votes

sematext-otel

Wire a service's OpenTelemetry output to Sematext Cloud. Walks through region, App-type, instrumentation flow (managed OTLP endpoint vs Sematext Agent), and signal selection (traces/metrics/logs), then produces the exact env-var block and points at a runnable reference example in this repo. Invoke when instrumenting a new app for Sematext.

01 votes

Deployment Patterns

Deployment workflows, CI/CD pipeline patterns, Docker containerization, health checks, rollback strategies, and production readiness checklists for web applications. Use when setting up deployment infrastructure or planning releases.

2459130 votes

Babysit

Watch a pull request or review cycle until it is ready to merge. Use when asked to babysit, monitor, or keep checking PR comments, reviews, and CI until all actionable issues are resolved.

929660 votes

V7 Roster

Interact with the Paperclip control plane API for task coordination and governance. Use when checking assignments, updating issue status, posting comments, delegating work, managing routines, or calling Paperclip API endpoints.

805540 votes
View all in devops →