A GitHub Action to dynamically place content in markdown slots
Table of Contents
To use this action, create slot tags in the markdown you wish to use as the source template.
<!-- slot: myContent -->
denotes the start of the markdown slot where myContent
is a user-defined name. This name will be used in the workflow step to assign content to this slot.
<!-- /slot -->
denotes the end of the slot.
All content will be placed within these tags. In other words, any thing within these tags will be overwritten by the slot contents.
# Example Markdown
<!-- slot: text -->
<!-- /slot -->
Markdown-slot tags are just HTML comments, and are ignored by markdown parsers (i.e. they won't be visible in the rendered markdown).
Use this action in a workflow step and provide a YAML compatible array mapping slot-names to their corresponding content. In the example below, the text Hello World!
is assigned to the slot named text
.
- name: markdown-slots
id: markdown-slots
uses: Shresht7/markdown-slots@v1
with:
slots: |
- slot: text
content: Hello World!
When the action runs, it will write the dynamically generated content to the slot. The generated markdown will be output as contents
. The action will also write contents to the specified destination dest
input.
Writing to the dest file is a local operation. You may want to follow-up with a add-and-commit or create-pull-request workflow-step.
# Example Markdown
<!-- slot: text -->
Hello World!
<!-- /slot -->
The default behaviour is to keep the slot tags even after content has been placed in the markdown file. This allows regeneration of slot content on subsequent runs. This can be disabled using the
remove-slots
input.
The only required input is slots
. slots
is a stringified YAML array that maps slot-names to their corresponding contents.
slots: |
- slot: date
content: Today is ${{ steps.<step_id>.outputs.date }}
- slot: month
content: $${{ steps.<step_id>.outputs.month }}
- slot: year
content: ${{ steps.<step_id>.outputs.year }}
<step_id> is a fictional step that outputs
date
,month
andyear
Note that the
|
is important. GitHub Actions expectstrings
notyaml-objects
. The|
signifies thatslots
is a multiline string, which is concatenated and parsed as yaml in the action.
In addition to slot
and content
, each slot input can take the following props
Property | Description |
---|---|
prepend |
Adds the prepend content before the slot-contents |
append |
Adds the append content after the slot-contents |
removeSlots |
Should remove the slot tags upon substitution |
for example, to wrap some code in a code-block:
slots: |
- slot: code
content: console.log(content)
props:
prepend: "```js"
append: "```"
Alternatively, slot props can also be specified on the slot-tag itself. These props take priority over the ones set in the workflow.
<!-- slot: code, prepend: ```js, append: ``` -->
<!-- /slot -->
The slot props follow the
key: value
format and are separated by,
.
Input | Description | Default | Required |
---|---|---|---|
src |
Path to the source file with markdown-slots (can be a URL) | ./README.md |
|
dest |
Desired output path for the generated content | ./README.md |
|
slots |
stringified YAML array mapping slot-names to content | undefined |
β |
remove-slots |
Boolean to determine if this action should remove slot tags upon replacement | false |
|
dry-run |
Boolean to determine if this is a dry-run | false |
The action outputs the generated contents as contents
. You can access this in subsequent steps using expressions.
e.g. ${{ steps.markdown-slots.outputs.contents }}
(This assumes you set the id
as markdown-slots
in the workflow step).
Output | Description |
---|---|
contents |
Generated markdown content |
The description, inputs and outputs tables of this README are placed in slots using this action! See the action-readme workflow for more details.
Click here to see the workflow
# =============
# ACTION README
# =============
# Workflow to automatically update the README with action.yml metadata
name: Action Readme
# Activation Events
# =================
on:
# When the action.yml or this workflow file changes
push:
branches:
- main
paths:
- action.yml
- .github/workflows/action-readme.yml
# Manual workflow dispatch
workflow_dispatch:
inputs:
dry-run:
description: dry-run
required: true
default: "false"
# Jobs
# ====
jobs:
update-readme:
runs-on: ubuntu-latest
steps:
# Actions Checkout β
# ===================
- name: checkout
uses: actions/checkout@v3
# Generate Action Metadata π
# ===========================
- name: action-metadata
id: action-metadata
uses: Shresht7/action-metadata@v1
# Read Example Workflow File π
# =============================
- name: read-file
id: read-file
uses: Shresht7/read-file-action@v1
with:
path: .github/workflows/action-readme.yml
# Markdown Slots π
# =================
- name: markdown-slots
id: markdown-slots
uses: Shresht7/markdown-slots@v1
with:
slots: |
- slot: description
content: ${{ steps.action-metadata.outputs.description }}
- slot: inputs
content: ${{ steps.action-metadata.outputs.inputs-md-table }}
- slot: outputs
content: ${{ steps.action-metadata.outputs.outputs-md-table }}
- slot: action-readme-workflow
content: ${{ toJSON(steps.read-file.outputs.contents) }}
props:
prepend: "```yaml"
append: "```"
# Push Changes π
# ===============
- name: check for changes
id: git-diff
run: |
if git diff --exit-code; then
echo "::set-output name=changes_exist::false"
else
echo "::set-output name=changes_exist::true"
fi
- name: add, commit and push
if: ${{ steps.git-diff.outputs.changes_exist == 'true' }}
run: |
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add .
git commit -m 'Update README.md π'
git push