Embed source files into any text file using comment markers. Works with markdown, YAML, Python, Rust, shell scripts, and any file that supports comments.
Place opening and closing markers in your file using whatever comment style is appropriate:
Markdown / HTML:
<!-- embed-src src="path/to/config.yml" -->
<!-- /embed-src -->Rust / JS / Go / C:
// embed-src src="path/to/utils.py"
// /embed-srcPython / Shell / YAML:
# embed-src src="path/to/setup.sh"
# /embed-srcCSS:
/* embed-src src="path/to/theme.css" */
/* /embed-src */SQL / Lua:
-- embed-src src="path/to/schema.sql"
-- /embed-srcWhen the tool runs, the content between the markers is replaced with the referenced file's contents.
By default, content is inserted raw (no wrapping). This works for any file type.
To wrap content in markdown code fences, use the fence attribute:
| Attribute | Behavior |
|---|---|
| (none) | Raw insertion |
fence |
Code fence with auto-detected language |
fence="auto" |
Code fence with auto-detected language |
fence="python" |
Code fence with explicit language tag |
Example with fencing:
<!-- embed-src src="path/to/config.yml" fence="auto" -->
```yaml
server:
host: localhost
port: 8080
```
<!-- /embed-src -->- Paths are relative to the host file's directory.
- The code fence language is inferred from the file extension when using
fenceorfence="auto". - Re-running is idempotent -- existing content between markers is replaced.
- Any File Type: Embed into markdown, YAML, Python, Rust, or any file with comments.
- Raw or Fenced: Insert raw content by default, or wrap in code fences with
fence. - Custom Commit Options: Personalize commit messages, author details, and push behavior.
- Dry-Run Mode: Test embedding without creating commits.
- Seamless Integration: Drop into any GitHub Actions workflow.
| Name | Description | Required | Default |
|---|---|---|---|
files |
Space-separated list of files to process. | No | README.md |
commit-message |
Commit message for the embedded changes. | No | chore: embed source files |
commit-name |
Git committer name. | No | github-actions[bot] |
commit-email |
Git committer email. | No | github-actions[bot]@users.noreply.github.com |
commit-push |
Whether to push after committing. | No | true |
commit-dry |
Skip the commit (dry-run mode). | No | false |
github-token |
GitHub token for downloading the binary. | No | ${{ github.token }} |
name: "Example"
on: [push]
jobs:
embed:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
- name: "Embed code into files"
uses: urmzd/embed-src@v1.5.0
with:
files: "README.md"- uses: urmzd/embed-src@v2
with:
files: "README.md docs/API.md docs/GUIDE.md"Useful for CI validation -- embed the files and check for drift without committing:
- uses: urmzd/embed-src@v2
with:
commit-dry: "true"
commit-push: "false"The embed-src binary can also be used directly:
# Process files in place
embed-src README.md docs/*.md
# Check if files are up-to-date (CI mode)
embed-src --verify README.md
# Preview changes without writing
embed-src --dry-run README.mdAction fails with "nothing to commit"
This means no changes were needed. Ensure your files contain valid embed-src markers with src="..." and corresponding /embed-src closing markers.
Permission denied on push
The action needs contents: write permission. Add this to your job:
permissions:
contents: writeFiles not being embedded
Verify the file paths in files are relative to the repository root and that the referenced source files exist.
We use Embed Src in our own CI/CD pipelines, ensuring our documentation is always synchronized with the latest code.