diff --git a/.github/actions/docs-preview/action.yaml b/.github/actions/docs-preview/action.yaml new file mode 100644 index 0000000000000..4e59ce2533afd --- /dev/null +++ b/.github/actions/docs-preview/action.yaml @@ -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<> $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<> $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<> $GITHUB_OUTPUT + echo -e "$PREVIEW_LINKS" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + else + echo "has_new_docs=false" >> $GITHUB_OUTPUT + fi \ No newline at end of file diff --git a/.github/workflows/docs-preview.yaml b/.github/workflows/docs-preview.yaml new file mode 100644 index 0000000000000..05194c9f4c8d4 --- /dev/null +++ b/.github/workflows/docs-preview.yaml @@ -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 || '' }} + + --- + 🤖 This comment is automatically generated and updated when documentation changes. + edit-mode: replace + reactions: eyes + reactions-edit-mode: replace \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy