-
Notifications
You must be signed in to change notification settings - Fork 928
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
d0fe1f8
Add simplified docs preview GitHub action
EdwardAngert 3010c77
Merge branch 'main' into simplified-docs-preview
EdwardAngert afbdde9
\Fix tj-actions/changed-files SHA to match existing usage\n\nUpdate t…
EdwardAngert 1f716c9
\Fix docs preview workflow to ensure PR comments are posted\n\nUpdate…
EdwardAngert 38cfd56
\Update preview URL format and add direct doc links\
EdwardAngert File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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 comment
The 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