Build Preview for "Repo sync" (#454) #619
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
name: Build Preview | |
run-name: 'Build Preview for "${{ github.event.pull_request.title }}" (#${{ github.event.pull_request.number }})' | |
on: | |
pull_request_target: | |
types: [opened, synchronize] | |
branches: | |
- main | |
- develop | |
# paths: | |
# Hello Security 👋, we are checking to make sure forked repo PR changed paths are only in content/** inside the job security-check. | |
# We are doing this so we can also reuse this workflow for internal PRs, as pull_request_target also triggers on internal PRs. (As does pull_request) | |
concurrency: | |
group: ${{ github.workflow }}-${{github.event_name}}-${{ github.event.pull_request.number || github.ref }} | |
cancel-in-progress: true | |
permissions: | |
pull-requests: write | |
contents: read # for embargoed content repos | |
jobs: | |
get-changed-files: | |
name: Get Changed Files | |
runs-on: ubuntu-latest | |
outputs: | |
changed_markdown_content_files: ${{ steps.changed-files.outputs.markdown_content_all_changed_files }} | |
changed_content_files_count: ${{ steps.changed-files.outputs.content_all_changed_files_count }} | |
not_content_bad_boy_naughty_files_count: ${{ steps.changed-files.outputs.not_content_bad_boy_naughty_all_changed_files_count }} | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- name: Get changed files in the content/ subdirectories | |
id: changed-files | |
uses: tj-actions/changed-files@dcc7a0cba800f454d79fff4b993e8c3555bcc0a8 # v45.0.7 | |
with: | |
files_yaml: | | |
content: | |
- 'content/**' | |
markdown_content: | |
- 'content/**/*.mdx' | |
not_content_bad_boy_naughty: | |
- '!content/**' | |
base_sha: ${{ github.event.pull_request.base.sha }} | |
sha: ${{ github.event.pull_request.head.sha }} | |
security-check: | |
name: Security Check | |
runs-on: ubuntu-latest | |
needs: [get-changed-files] | |
steps: | |
- name: If in a forked repo fail if any changes are outside of content/** | |
run: | | |
: # Cases: | |
: # 1. PR from forked repo, changes outside of content/**; fail | |
if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ] && [ ${{ needs.get-changed-files.outputs.not_content_bad_boy_naughty_files_count }} -gt 0 ]; then | |
echo "❌ This is a PR from a forked repo with changes outside of content/\*\*. **Please only edit files in the content/\*\* directory.**" >> $GITHUB_STEP_SUMMARY | |
exit 1 | |
: # 2. PR from forked repo, changes only in content/**; pass | |
elif [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ] && [ ${{ needs.get-changed-files.outputs.not_content_bad_boy_naughty_files_count }} -eq 0 ]; then | |
echo "✅ This is a PR from a forked repo with NO changes outside of content/\*\*. Proceeding with the workflow." >> $GITHUB_STEP_SUMMARY | |
exit 0 | |
fi | |
: # 3. PR from internal repo, changes outside of content/**; pass | |
: # 4. PR from internal repo, changes only in content/**; pass | |
echo "✅ This is an internal PR. Proceeding with the workflow." >> $GITHUB_STEP_SUMMARY | |
exit 0 | |
deploy-unified-docs-api-preview: | |
name: Deploy Unified Docs API Preview | |
runs-on: ubuntu-latest | |
needs: [security-check] | |
outputs: | |
preview_url: ${{ steps.unified_docs_preview_url.outputs.preview_url }} | |
preview_url_to_fetch_deployment: ${{ steps.unified_docs_preview_url.outputs.preview_url_to_fetch_deployment }} | |
inspector_url: ${{ steps.unified_docs_inspector_url.outputs.inspector_url }} | |
created_utc: ${{ steps.unified_docs_preview_url.outputs.created_utc }} | |
steps: | |
- name: Initial comment on PR | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: preview-notice | |
message: | | |
## Deploying Vercel Previews... | |
| Name | Status | Preview | Updated (UTC) | | |
| :--- | :----- | :------ | :------------ | | |
| Dev Portal | 🔄 Building ([Inspect](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})) | --- | --- | | |
| Unified Docs API | 🔄 Building ([Inspect](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})) | --- | --- | | |
- name: Checkout hashicorp/web-unified-docs | |
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 | |
with: | |
ref: ${{ github.event.pull_request.head.sha }} | |
- name: Add commit link to summary | |
run: | | |
echo "[Built using commit $(echo ${{ github.event.pull_request.head.sha }} | cut -c -7)](https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}/commits/${{ github.event.pull_request.head.sha }})" >> $GITHUB_STEP_SUMMARY | |
- name: Setup Node.js | |
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 | |
with: | |
cache: 'npm' | |
node-version-file: 'package.json' | |
- name: Use cache | |
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 | |
with: | |
path: | | |
~/.npm | |
${{ github.workspace }}/.next/cache | |
# Generate a new cache whenever packages or source files change. | |
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.mjs', '**/*.ts', '**/*.tsx', '**/*.mdx', '**/*.json') }} | |
# If source files changed but packages didn't, rebuild from a prior cache. | |
restore-keys: | | |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}- | |
- name: Install Vercel CLI | |
run: npm i --global vercel@latest | |
- name: Link web-unified-docs Vercel Project | |
run: vercel link --yes --project web-unified-docs --token=${{ secrets.VERCEL_TOKEN }} | |
- name: Pull Vercel Environment Information | |
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} | |
- name: Build Project Artifacts | |
run: vercel build --target=preview --token=${{ secrets.VERCEL_TOKEN }} | |
- name: Deploy Project Artifacts and Set GitHub Outputs | |
id: unified_docs_preview_url | |
# save preview url from deployment and save copy of the preview url w/o https to fetch the deployment via Vercel REST API in next step | |
run: | | |
preview_url=$(vercel deploy --prebuilt --target=preview --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz) | |
echo "preview_url=$preview_url" >> $GITHUB_OUTPUT | |
created_utc=$(date -u) | |
echo "created_utc=$created_utc" >> $GITHUB_OUTPUT | |
preview_url_to_fetch_deployment=$(echo "$preview_url" | sed 's/^https:\/\///') | |
echo "preview_url_to_fetch_deployment=$preview_url_to_fetch_deployment" >> $GITHUB_OUTPUT | |
echo "deployment url is $preview_url" | |
echo "deployment url for REST API request is $preview_url_to_fetch_deployment" | |
echo "created at is $created_utc" | |
# as of March 2025, the Vercel CLI does not return the inspect URL in the output of the vercel deploy command, which is needed for the PR comment | |
# we need to fetch the deployment info via the Vercel REST API using the preview_url_to_fetch_deployment output from the last step and parse the inspect URL from it (inspectorUrl prop name) | |
- name: Vercel REST API Request to Fetch Inspect URL and Set GitHub Output | |
id: unified_docs_inspector_url | |
run: | | |
response=$(curl -sS -G "https://api.vercel.com/v13/deployments/${{ steps.unified_docs_preview_url.outputs.preview_url_to_fetch_deployment }}" \ | |
-H "Authorization: Bearer ${{ secrets.VERCEL_TOKEN }}" \ | |
-H "Content-Type: application/json" \ | |
-d "teamId=${{ secrets.VERCEL_TEAM_ID }}") | |
inspector_url=$(echo "$response" | jq -r ".inspectorUrl") | |
echo "inspector_url=$inspector_url" >> $GITHUB_OUTPUT | |
echo "Inspect URL is $inspector_url" | |
- name: Update Comment with Unified Docs API Data | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: preview-notice | |
message: | | |
## Vercel Previews Deployed | |
| Name | Status | Preview | Updated (UTC) | | |
| :--- | :--- | :--- | :--- | | |
| Dev Portal | 🔄 Building ([Inspect](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})) | --- | --- | | |
| Unified Docs API | ✅ Ready ([Inspect](${{ steps.unified_docs_inspector_url.outputs.inspector_url }} )) | [Visit Preview](${{ steps.unified_docs_preview_url.outputs.preview_url }}) | ${{ steps.unified_docs_preview_url.outputs.created_utc }} | | |
deploy-dev-portal-preview: | |
name: Deploy Dev Portal Preview | |
runs-on: ubuntu-latest | |
needs: [deploy-unified-docs-api-preview] | |
outputs: | |
preview_url: ${{ steps.deploy_dev_portal_preview.outputs.preview_url }} | |
steps: | |
- name: Checkout hashicorp/dev-portal (Frontend) | |
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 | |
with: | |
repository: hashicorp/dev-portal | |
path: ./unified-docs-frontend-preview | |
- name: Use cache | |
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 | |
with: | |
path: | | |
~/.npm | |
${{ github.workspace }}/unified-docs-frontend-preview/.next/cache | |
# Generate a new cache whenever packages or source files change. | |
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx', '**/*.mdx') }} | |
# If source files changed but packages didn't, rebuild from a prior cache. | |
restore-keys: | | |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}- | |
- name: Setup Node.js | |
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 | |
with: | |
cache: 'npm' | |
cache-dependency-path: 'unified-docs-frontend-preview/package-lock.json' | |
node-version-file: 'unified-docs-frontend-preview/package.json' | |
- name: Setup Vercel CLI | |
run: npm i --global vercel@latest | |
- run: vercel pull --yes --environment=preview --scope=hashicorp --token=${{ secrets.VERCEL_TOKEN }} | |
working-directory: unified-docs-frontend-preview | |
- name: inject env vars | |
run: | | |
cd unified-docs-frontend-preview | |
echo "HASHI_ENV=unified-docs-sandbox" >> .env | |
echo "UNIFIED_DOCS_API=${{ needs.deploy-unified-docs-api-preview.outputs.preview_url }}" >> .env | |
echo "VERCEL_AUTOMATION_BYPASS_SECRET=${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}" >> .env | |
- name: Build dev-portal | |
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 | |
env: | |
# Used to read docs from private repos, once all docs are in UDR we can remove this | |
GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }} | |
with: | |
shell: bash | |
timeout_minutes: 10 | |
max_attempts: 2 | |
command: | | |
cd unified-docs-frontend-preview | |
vercel build --token=${{ secrets.VERCEL_TOKEN }} | |
- name: Deploy Project Artifacts and Set GitHub Outputs | |
id: deploy_dev_portal_preview | |
run: | | |
preview_url=$(vercel deploy --prebuilt --archive=tgz --scope=hashicorp --token=${{ secrets.VERCEL_TOKEN }}) | |
echo "preview_url=$preview_url" >> $GITHUB_OUTPUT | |
created_utc=$(date -u) | |
echo "created_utc=$created_utc" >> $GITHUB_OUTPUT | |
preview_url_to_fetch_deployment=$(echo "$preview_url" | sed 's/^https:\/\///') | |
echo "preview_url_to_fetch_deployment=$preview_url_to_fetch_deployment" >> $GITHUB_OUTPUT | |
echo "deployment url is $preview_url" | |
echo "deployment url for REST API request is $preview_url_to_fetch_deployment" | |
echo "created at is $created_utc" | |
working-directory: unified-docs-frontend-preview | |
# as of March 2025, the Vercel CLI does not return the inspect URL in the output of the vercel deploy command, which is needed for the PR comment | |
# we need to fetch the deployment info via the Vercel REST API using the preview_url_to_fetch_deployment output from the last step and parse the inspect URL from it (inspectorUrl prop name) | |
- name: Vercel REST API Request to Fetch Inspect URL and Set GitHub Output | |
id: dev_portal_inspector_url | |
run: | | |
response=$(curl -sS -G "https://api.vercel.com/v13/deployments/${{ steps.deploy_dev_portal_preview.outputs.preview_url_to_fetch_deployment }}" \ | |
-H "Authorization: Bearer ${{ secrets.VERCEL_TOKEN }}" \ | |
-H "Content-Type: application/json" \ | |
-d "teamId=${{ secrets.VERCEL_TEAM_ID }}") | |
inspector_url=$(echo "$response" | jq -r ".inspectorUrl") | |
echo "inspector_url=$inspector_url" >> $GITHUB_OUTPUT | |
echo "Inspect URL is $inspector_url" | |
- name: Update PR Comment with Dev Portal Data | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: preview-notice | |
message: | | |
## Vercel Previews Deployed | |
| Name | Status | Preview | Updated (UTC) | | |
| :--- | :--- | :--- | :--- | | |
| Dev Portal | ✅ Ready ([Inspect](${{ steps.dev_portal_inspector_url.outputs.inspector_url }})) | [Visit Preview](${{ steps.deploy_dev_portal_preview.outputs.preview_url }}) | ${{ steps.deploy_dev_portal_preview.outputs.created_utc }} | | |
| Unified Docs API | ✅ Ready ([Inspect](${{ needs.deploy-unified-docs-api-preview.outputs.inspector_url }} )) | [Visit Preview](${{ needs.deploy-unified-docs-api-preview.outputs.preview_url }}) | ${{ needs.deploy-unified-docs-api-preview.outputs.created_utc }} | | |
check-links: | |
name: Run Link Checker | |
needs: [get-changed-files, deploy-dev-portal-preview] | |
if: needs.get-changed-files.outputs.changed_content_files_count > 0 | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
ref: ${{ github.event.pull_request.head.sha }} | |
- name: Checking links in files | |
run: | | |
echo "Checking links in files:" | |
echo "${{ needs.get-changed-files.outputs.changed_markdown_content_files }}" | tr ' ' '\n' | |
- name: Run lychee link checker | |
id: lychee | |
uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0 | |
with: | |
args: >- | |
${{ needs.get-changed-files.outputs.changed_markdown_content_files }} | |
-b ${{ needs.deploy-dev-portal-preview.outputs.preview_url }} | |
--exclude-all-private | |
--exclude '\.(svg|gif|jpg|png)' | |
--exclude 'gnu\.org' | |
--accept 200,408,429 | |
--timeout=60 | |
--max-concurrency 24 | |
--no-progress | |
--verbose | |
--header x-vercel-protection-bypass=${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }} | |
fail: false | |
env: | |
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} | |
- name: Print lychee exit code | |
run: | | |
echo "Lychee exit code:" | |
echo ${{ steps.lychee.outputs.exit_code }} | |
- name: Add Broken Link Checker header to lychee output | |
if: steps.lychee.outputs.exit_code != 0 | |
run: | | |
sed -i '1s/^/## Broken Link Checker\n/' ./lychee/out.md | |
# Get length of lychee output | |
- name: lychee output size check | |
id: char-count | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
if: steps.lychee.outputs.exit_code != 0 | |
with: | |
script: | | |
const size = require('fs').readFileSync('./lychee/out.md').length; | |
console.log(`${size} characters`); | |
core.setOutput('size', size); | |
# If the char count of the lychee report is too long, it's going to break | |
# the sticky-pull-request-comment action because of a body size limitation | |
# on the GitHub PR comment API. So, instead, upload the full report to GH | |
# artifacts and just link to that instead | |
- name: Upload lychee report to GitHub artifacts | |
id: upload-artifact | |
if: steps.lychee.outputs.exit_code != 0 && fromJson(steps.char-count.outputs.size) >= fromJson(vars.BROKEN_LINK_REPORT_CHAR_MAX) | |
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 | |
with: | |
path: ./lychee/out.md | |
name: Link Checker Report | |
- name: Comment on PR with link to full link checker report | |
if: steps.lychee.outputs.exit_code != 0 && fromJson(steps.char-count.outputs.size) >= fromJson(vars.BROKEN_LINK_REPORT_CHAR_MAX) | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: Link Checker Report | |
message: | | |
## Broken Link Checker | |
Report exceeds max length of ${{vars.BROKEN_LINK_REPORT_CHAR_MAX}} characters, so it cannot be displayed in GitHub comments. [Download full report.](${{steps.upload-artifact.outputs.artifact-url}}) | |
- name: Comment on PR with link checker report | |
if: steps.lychee.outputs.exit_code != 0 && fromJson(steps.char-count.outputs.size) < fromJson(vars.BROKEN_LINK_REPORT_CHAR_MAX) | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: Link Checker Report | |
path: ./lychee/out.md | |
# Fail github action if lychee exit code is anything other than the success code (0) | |
- name: lychee exit code check | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
if: steps.lychee.outputs.exit_code != 0 | |
with: | |
script: | | |
core.setFailed('lychee failed with exit code ${{steps.lychee.outputs.exit_code}}') | |
# If all previous Github actions run (indicating success), this one will run and overwrite the comment with a success message | |
- name: Comment on PR about successful link check | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: Link Checker Report | |
message: | | |
## Broken Link Checker | |
No broken links found! 🎉 | |
# Delete the Link Checker PR comment if no files have changed | |
skip-check-links: | |
name: Skip Link Checker | |
needs: [get-changed-files, deploy-dev-portal-preview] | |
if: needs.get-changed-files.outputs.changed_content_files_count == 0 | |
runs-on: ubuntu-latest | |
steps: | |
- name: Update PR comment | |
uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 | |
with: | |
header: Link Checker Report | |
delete: true |