- Notifications
You must be signed in to change notification settings - Fork1k
docs: add docs preview GitHub action#17317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
d0fe1f8
3010c77
afbdde9
1f716c9
38cfd56
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Do we plan to reuse this action anywhere else? If not I would move it to the main workflow file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. this PR's just to get it started - we've got another PR with workflow improvements in#17322 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
name: 'Docs Preview Action' | ||
description: 'A composite action to provide Vercel preview links for documentation changes' | ||
author: 'Coder' | ||
inputs: | ||
github-token: | ||
description: 'GitHub token for API operations' | ||
required: true | ||
docs-dir: | ||
description: 'Path to the docs directory' | ||
required: false | ||
default: 'docs' | ||
vercel-domain: | ||
description: 'DEPRECATED - Previously for Vercel, now using different URL format' | ||
required: false | ||
default: 'coder-docs-git' | ||
changed-files: | ||
description: 'JSON string of changed files (from tj-actions/changed-files)' | ||
required: true | ||
manifest-changed: | ||
description: 'Boolean indicating if manifest.json has changed (from tj-actions/changed-files)' | ||
required: true | ||
outputs: | ||
has_changes: | ||
description: 'Boolean indicating if documentation files have changed' | ||
value: ${{ steps.docs-analysis.outputs.has_changes }} | ||
changed_files: | ||
description: 'List of changed documentation files formatted for comment' | ||
value: ${{ steps.docs-analysis.outputs.changed_files }} | ||
url: | ||
description: 'Vercel preview URL' | ||
value: ${{ steps.vercel-preview.outputs.url }} | ||
has_new_docs: | ||
description: 'Boolean indicating if new docs were added in manifest.json' | ||
value: ${{ steps.manifest-analysis.outputs.has_new_docs || 'false' }} | ||
new_docs: | ||
description: 'List of newly added docs formatted for comment' | ||
value: ${{ steps.manifest-analysis.outputs.new_docs || '' }} | ||
preview_links: | ||
description: 'List of preview links for newly added docs' | ||
value: ${{ steps.manifest-analysis.outputs.preview_links || '' }} | ||
runs: | ||
using: 'composite' | ||
steps: | ||
- name: Set security environment | ||
shell: bash | ||
run: | | ||
# Secure the environment by clearing potentially harmful variables | ||
unset HISTFILE | ||
umask 077 | ||
# Validate that docs directory exists | ||
if [ ! -d "${{ inputs.docs-dir }}" ]; then | ||
echo "::error::Docs directory '${{ inputs.docs-dir }}' does not exist" | ||
exit 1 | ||
fi | ||
- name: Debug inputs | ||
shell: bash | ||
run: | | ||
echo "Docs dir: ${{ inputs.docs-dir }}" | ||
echo "Manifest changed: ${{ inputs.manifest-changed }}" | ||
echo "First few changed files:" | ||
echo '${{ inputs.changed-files }}' | jq -r '.[] | select(startswith("${{ inputs.docs-dir }}/"))' | head -n 5 | ||
- name: Analyze docs changes | ||
id: docs-analysis | ||
shell: bash | ||
run: | | ||
# Parse changed files from input and write to temp file with strict permissions | ||
echo '${{ inputs.changed-files }}' > changed_files.json | ||
# Count total changed doc files | ||
DOC_FILES_COUNT=$(jq -r '.[] | select(startswith("${{ inputs.docs-dir }}/"))' changed_files.json | wc -l) | ||
echo "doc_files_count=$DOC_FILES_COUNT" >> $GITHUB_OUTPUT | ||
# Force to true for debugging | ||
DOC_FILES_COUNT=1 | ||
# Get branch name for URLs | ||
BRANCH_NAME=$(jq --raw-output .pull_request.head.ref "$GITHUB_EVENT_PATH") | ||
# Format changed files for comment with clickable links | ||
FORMATTED_FILES="" | ||
while read -r file_path; do | ||
[ -z "$file_path" ] && continue | ||
# Create direct link to file | ||
# Remove .md extension and docs/ prefix for the URL path | ||
url_path=$(echo "$file_path" | sed 's/^docs\///' | sed 's/\.md$//') | ||
file_url="https://coder.com/docs/@${BRANCH_NAME}/${url_path}" | ||
# Add the formatted line with link | ||
FORMATTED_FILES="${FORMATTED_FILES}- [$file_path]($file_url)\n" | ||
done < <(jq -r '.[] | select(startswith("${{ inputs.docs-dir }}/"))' changed_files.json) | ||
# Add a minimum placeholder if no files found | ||
if [ -z "$FORMATTED_FILES" ]; then | ||
# Hardcode a test example that links directly to the parameters.md file | ||
FORMATTED_FILES="- [docs/admin/templates/extending-templates/parameters.md](https://coder.com/docs/@${BRANCH_NAME}/admin/templates/extending-templates/parameters)\n" | ||
fi | ||
echo "changed_files<<EOF" >> $GITHUB_OUTPUT | ||
echo -e "$FORMATTED_FILES" >> $GITHUB_OUTPUT | ||
echo "EOF" >> $GITHUB_OUTPUT | ||
# Determine if docs have changed - force true for testing | ||
echo "has_changes=true" >> $GITHUB_OUTPUT | ||
# Clean up sensitive file | ||
rm -f changed_files.json | ||
- name: Generate Vercel preview URL | ||
id: vercel-preview | ||
if: steps.docs-analysis.outputs.has_changes == 'true' | ||
shell: bash | ||
run: | | ||
# Get PR branch name for Vercel preview URL | ||
BRANCH_NAME=$(jq --raw-output .pull_request.head.ref "$GITHUB_EVENT_PATH") | ||
# Input validation - ensure branch name is valid | ||
if [ -z "$BRANCH_NAME" ]; then | ||
echo "::error::Could not determine branch name" | ||
exit 1 | ||
fi | ||
# For debugging | ||
echo "Branch name: $BRANCH_NAME" | ||
# Create the correct Vercel preview URL | ||
VERCEL_PREVIEW_URL="https://coder.com/docs/@$BRANCH_NAME" | ||
echo "url=$VERCEL_PREVIEW_URL" >> $GITHUB_OUTPUT | ||
- name: Analyze manifest changes | ||
id: manifest-analysis | ||
if: inputs.manifest-changed == 'true' | ||
shell: bash | ||
run: | | ||
# Get PR number for links | ||
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") | ||
# Get the base SHA for diff | ||
BASE_SHA=$(git merge-base HEAD origin/main) | ||
# Extract new docs from manifest.json diff with safe patterns | ||
NEW_DOCS=$(git diff "$BASE_SHA"..HEAD -- "${{ inputs.docs-dir }}/manifest.json" | grep -E '^\+.*"path":' | sed -E 's/.*"path": *"(.*)".*/\1/g') | ||
if [ -n "$NEW_DOCS" ]; then | ||
echo "has_new_docs=true" >> $GITHUB_OUTPUT | ||
# Format new docs for comment | ||
FORMATTED_NEW_DOCS=$(echo "$NEW_DOCS" | sort | uniq | grep -v "^$" | sed 's/^/- `/g' | sed 's/$/`/g') | ||
echo "new_docs<<EOF" >> $GITHUB_OUTPUT | ||
echo "$FORMATTED_NEW_DOCS" >> $GITHUB_OUTPUT | ||
echo "EOF" >> $GITHUB_OUTPUT | ||
# Generate preview links for new docs | ||
PREVIEW_LINKS="" | ||
while IFS= read -r doc_path; do | ||
# Skip empty lines | ||
[ -z "$doc_path" ] && continue | ||
# Clean the path and sanitize | ||
clean_path=${doc_path#./} | ||
clean_path=$(echo "$clean_path" | tr -cd 'a-zA-Z0-9_./-') | ||
# Get branch name for URLs | ||
BRANCH_NAME=$(jq --raw-output .pull_request.head.ref "$GITHUB_EVENT_PATH") | ||
# Generate preview URL with correct format | ||
url_path=$(echo "$clean_path" | sed 's/\.md$//') | ||
preview_url="https://coder.com/docs/@${BRANCH_NAME}/${url_path}" | ||
# Extract doc title or use filename safely | ||
if [ -f "$doc_path" ]; then | ||
title=$(grep -m 1 "^# " "$doc_path" | sed 's/^# //') | ||
title=$(echo "$title" | tr -cd 'a-zA-Z0-9 _.,-') | ||
[ -z "$title" ] && title=$(basename "$doc_path" .md | tr -cd 'a-zA-Z0-9_.-') | ||
else | ||
title=$(basename "$doc_path" .md | tr -cd 'a-zA-Z0-9_.-') | ||
fi | ||
PREVIEW_LINKS="${PREVIEW_LINKS}- [$title]($preview_url)\n" | ||
done <<< "$NEW_DOCS" | ||
echo "preview_links<<EOF" >> $GITHUB_OUTPUT | ||
echo -e "$PREVIEW_LINKS" >> $GITHUB_OUTPUT | ||
echo "EOF" >> $GITHUB_OUTPUT | ||
else | ||
echo "has_new_docs=false" >> $GITHUB_OUTPUT | ||
fi |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
name: Docs Preview | ||
on: | ||
pull_request: | ||
types: [opened, synchronize, reopened] | ||
paths: | ||
- 'docs/**' | ||
permissions: | ||
contents: read | ||
jobs: | ||
preview: | ||
name: Generate docs preview | ||
runs-on: ubuntu-latest | ||
permissions: | ||
pull-requests: write # needed for commenting on PRs | ||
steps: | ||
- name: Harden Runner | ||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 | ||
with: | ||
egress-policy: audit | ||
- name: Checkout | ||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
with: | ||
fetch-depth: 0 | ||
- name: Get PR info | ||
id: pr_info | ||
run: | | ||
set -euo pipefail | ||
PR_NUMBER=${{ github.event.pull_request.number }} | ||
echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_ENV | ||
echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_OUTPUT | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Get changed files | ||
id: changed-files | ||
uses: tj-actions/changed-files@27ae6b33eaed7bf87272fdeb9f1c54f9facc9d99 # v45.0.7 | ||
with: | ||
files: | | ||
docs/** | ||
- name: Debug changed files | ||
run: | | ||
echo "All changed files: ${{ steps.changed-files.outputs.all_changed_files }}" | ||
echo "JSON format: ${{ steps.changed-files.outputs.all_changed_files_json }}" | ||
- name: Check if manifest changed | ||
id: manifest-check | ||
run: | | ||
echo "changed=${{ contains(steps.changed-files.outputs.all_changed_files, 'docs/manifest.json') }}" >> $GITHUB_OUTPUT | ||
- name: Generate docs preview | ||
id: docs-preview | ||
uses: ./.github/actions/docs-preview | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
changed-files: ${{ steps.changed-files.outputs.all_changed_files_json }} | ||
manifest-changed: ${{ steps.manifest-check.outputs.changed }} | ||
- name: Debug outputs | ||
run: | | ||
echo "Has changes: ${{ steps.docs-preview.outputs.has_changes }}" | ||
echo "URL: ${{ steps.docs-preview.outputs.url }}" | ||
echo "Changed files:" | ||
echo "${{ steps.docs-preview.outputs.changed_files }}" | ||
- name: Find existing comment | ||
if: steps.docs-preview.outputs.has_changes == 'true' | ||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0 | ||
id: find-comment | ||
with: | ||
issue-number: ${{ env.PR_NUMBER }} | ||
comment-author: 'github-actions[bot]' | ||
body-includes: '## 📚 Docs Preview' | ||
direction: last | ||
- name: Create or update preview comment | ||
if: steps.docs-preview.outputs.has_changes == 'true' | ||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
comment-id: ${{ steps.find-comment.outputs.comment-id }} | ||
issue-number: ${{ env.PR_NUMBER }} | ||
body: | | ||
## 📚 Docs Preview | ||
Your documentation changes are available for preview at: | ||
**🔗 [Documentation Preview](${{ steps.docs-preview.outputs.url }})** | ||
### Changed Documentation Files | ||
${{ steps.docs-preview.outputs.changed_files }} | ||
${{ steps.docs-preview.outputs.has_new_docs == 'true' && '### Newly Added Documentation' || '' }} | ||
${{ steps.docs-preview.outputs.has_new_docs == 'true' && steps.docs-preview.outputs.new_docs || '' }} | ||
${{ steps.docs-preview.outputs.has_new_docs == 'true' && '### Preview Links for New Docs' || '' }} | ||
${{ steps.docs-preview.outputs.has_new_docs == 'true' && steps.docs-preview.outputs.preview_links || '' }} | ||
--- | ||
<sub>🤖 This comment is automatically generated and updated when documentation changes.</sub> | ||
edit-mode: replace | ||
reactions: eyes | ||
reactions-edit-mode: replace |
Uh oh!
There was an error while loading.Please reload this page.