Sync Next.js Official Documentation #11
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: Sync Next.js Official Documentation | |
on: | |
workflow_dispatch: # Manual trigger | |
schedule: | |
# 8 AM Los Angeles (Pacific) time - corresponds to UTC-7 (PDT) or UTC-8 (PST) | |
# This cron format is in UTC, so 15:00 UTC during PDT, 16:00 UTC during PST | |
- cron: "0 15 * * *" | |
# Add permissions needed for creating PRs | |
permissions: | |
contents: write | |
pull-requests: write | |
jobs: | |
check-branch: | |
name: Check if PR branch exists | |
runs-on: ubuntu-latest | |
outputs: | |
should_sync: ${{ steps.check_branch.outputs.should_sync }} | |
steps: | |
- name: Check if PR branch exists | |
id: check_branch | |
run: | | |
if git ls-remote --heads https://github.com/${{ github.repository }}.git | grep -q "docs/sync-nextjs-documentation"; then | |
echo "Branch already exists, skipping update" | |
echo "should_sync=false" >> $GITHUB_OUTPUT | |
else | |
echo "Branch does not exist, proceeding with update" | |
echo "should_sync=true" >> $GITHUB_OUTPUT | |
fi | |
sync-docs: | |
name: Sync Next.js Docs | |
runs-on: ubuntu-latest | |
needs: check-branch | |
if: needs.check-branch.outputs.should_sync == 'true' | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Clone Next.js repository (canary) | |
run: | | |
git clone --depth 1 --branch canary --single-branch https://github.com/vercel/next.js.git nextjs-canary | |
mkdir -p apps/docs/content/en/docs | |
rsync -av --delete nextjs-canary/docs/ apps/docs/content/en/docs/ --exclude="13" --exclude="14" | |
rm -rf nextjs-canary | |
- name: Clone Next.js repository (v14.2.28) | |
run: | | |
git clone --depth 1 --branch v14.2.28 --single-branch https://github.com/vercel/next.js.git nextjs-v14 | |
mkdir -p apps/docs/content/en/docs/14 | |
rsync -av --delete nextjs-v14/docs/ apps/docs/content/en/docs/14/ | |
rm -rf nextjs-v14 | |
- name: Clone Next.js repository (v13.5.11) | |
run: | | |
git clone --depth 1 --branch v13.5.11 --single-branch https://github.com/vercel/next.js.git nextjs-v13 | |
mkdir -p apps/docs/content/en/docs/13 | |
rsync -av --delete nextjs-v13/docs/ apps/docs/content/en/docs/13/ | |
rm -rf nextjs-v13 | |
- name: Setup Tools | |
uses: ./.github/actions/setup | |
- name: Sync blog & learn | |
run: | | |
node packages/crawler/dist/index.js | |
- name: Find available translation locales | |
id: find_locales | |
run: | | |
cd apps/docs/content | |
LOCALES=$(find . -maxdepth 1 -type d | grep -v "^.$" | grep -v "/en$" | sed 's|^\./||' | tr '\n' ' ' | sed 's/ $//') | |
echo "Available translation locales: $LOCALES" | |
echo "locales=$LOCALES" >> $GITHUB_OUTPUT | |
- name: Stage changes to detect renames | |
run: | | |
# Stage all changes so Git can detect renames | |
git add . | |
# Show what Git sees after staging | |
echo "Git status after staging:" | |
git status --porcelain | |
- name: Process file renames and deletions | |
run: | | |
# Get list of renamed files from git status | |
RENAMES=$(git status --porcelain | grep -E "^R[[:space:]]+apps/docs/content/en" | sed 's/^R[[:space:]]*//') | |
# Get list of deleted files from git status | |
DELETES=$(git status --porcelain | grep -E "^D[[:space:]]+apps/docs/content/en" | sed 's/^D[[:space:]]*//') | |
# Generate current timestamp in ISO format | |
CURRENT_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") | |
echo "Current timestamp: $CURRENT_TIMESTAMP" | |
# Process renames | |
if [ -n "$RENAMES" ]; then | |
echo "File renames detected in English docs. Processing for other languages..." | |
# For each locale | |
for LOCALE in ${{ steps.find_locales.outputs.locales }}; do | |
echo "Processing renames for locale: $LOCALE" | |
# For each renamed file | |
echo "$RENAMES" | while read -r LINE; do | |
# Split the line into source and destination | |
# After sed processing, each LINE is in format: "oldname -> newname" | |
SOURCE=$(echo "$LINE" | awk -F ' -> ' '{print $1}') | |
DEST=$(echo "$LINE" | awk -F ' -> ' '{print $2}') | |
# Check if there are actual content changes using git diff with -M (detect renames) | |
# If there's output from the diff command beyond the rename header, there are content changes | |
DIFF_OUTPUT=$(git diff --cached -M -- "$SOURCE" "$DEST") | |
# Count lines that start with +/- (changes) but ignore the rename header lines | |
CHANGE_COUNT=$(echo "$DIFF_OUTPUT" | grep -v "^renamed:" | grep -v "^─" | grep -E "^\+|^-" | wc -l) | |
echo "Git diff for '$SOURCE' → '$DEST': $CHANGE_COUNT lines changed" | |
# Determine if this is just a rename or if content was also changed | |
if [ "$CHANGE_COUNT" -eq 0 ]; then | |
CONTENT_UNCHANGED=true | |
echo "Pure rename detected (no content changes)" | |
else | |
CONTENT_UNCHANGED=false | |
echo "Content changes detected along with rename" | |
fi | |
# Replace 'en' with current locale in paths | |
SOURCE_LOCALE=${SOURCE/content\/en/content\/$LOCALE} | |
DEST_LOCALE=${DEST/content\/en/content\/$LOCALE} | |
# Check if source file exists in this locale | |
if [ -f "$SOURCE_LOCALE" ]; then | |
echo "Renaming $SOURCE_LOCALE to $DEST_LOCALE" | |
# Create directory if it doesn't exist | |
mkdir -p $(dirname "$DEST_LOCALE") | |
# Move the file | |
mv "$SOURCE_LOCALE" "$DEST_LOCALE" | |
# If the content is identical (just a rename, not a modification) | |
# then update the timestamps in the translation file | |
if [ "$CONTENT_UNCHANGED" = "true" ]; then | |
echo "Content unchanged, updating timestamps in $DEST_LOCALE" | |
# Update source-updated-at and translation-updated-at in the file | |
# Using portable sed syntax that works on both Linux and macOS | |
perl -i -pe "s/source-updated-at: .*/source-updated-at: $CURRENT_TIMESTAMP/" "$DEST_LOCALE" | |
perl -i -pe "s/translation-updated-at: .*/translation-updated-at: $CURRENT_TIMESTAMP/" "$DEST_LOCALE" | |
else | |
echo "Content changed, keeping original timestamps for translation to detect changes" | |
fi | |
fi | |
done | |
done | |
else | |
echo "No file renames detected in English docs." | |
fi | |
# Process deletions | |
if [ -n "$DELETES" ]; then | |
echo "File deletions detected in English docs. Processing for other languages..." | |
# For each locale | |
for LOCALE in ${{ steps.find_locales.outputs.locales }}; do | |
echo "Processing deletions for locale: $LOCALE" | |
# For each deleted file | |
echo "$DELETES" | while read -r FILE; do | |
# Replace 'en' with current locale in paths | |
FILE_LOCALE=${FILE/content\/en/content\/$LOCALE} | |
# Check if file exists in this locale | |
if [ -f "$FILE_LOCALE" ]; then | |
echo "Deleting $FILE_LOCALE" | |
rm -f "$FILE_LOCALE" | |
# Check if parent directory is empty and remove it if it is | |
DIR=$(dirname "$FILE_LOCALE") | |
if [ -d "$DIR" ] && [ -z "$(ls -A $DIR)" ]; then | |
echo "Removing empty directory: $DIR" | |
rmdir "$DIR" | |
fi | |
fi | |
done | |
done | |
else | |
echo "No file deletions detected in English docs." | |
fi | |
- name: Check for modifications | |
id: check_changes | |
run: | | |
if [[ $(git status --porcelain | grep -E "apps/docs/content/" | wc -l) -gt 0 ]]; then | |
echo "has_changes=true" >> $GITHUB_OUTPUT | |
echo "Changes detected. Will proceed with PR." | |
else | |
echo "has_changes=false" >> $GITHUB_OUTPUT | |
echo "No changes detected in docs. Skipping PR." | |
fi | |
- name: Create Pull Request | |
if: steps.check_changes.outputs.has_changes == 'true' | |
uses: peter-evans/create-pull-request@v5 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
commit-message: "docs: update nextjs documentation" | |
title: "docs: update nextjs documentation" | |
body: | | |
This PR updates the Next.js English documentation from the official Next.js repository. | |
- Updates from `canary` branch to `apps/docs/content/en/docs` | |
- Updates from `v14.2.28` branch to `apps/docs/content/en/docs/14` | |
- Updates from `v13.5.11` branch to `apps/docs/content/en/docs/13` | |
- Updates from blog to `apps/docs/content/en/blog` | |
- Updates from learn to `apps/docs/content/en/learn` | |
branch: docs/sync-nextjs-documentation | |
delete-branch: true | |
base: dev | |
add-paths: | | |
apps/docs/content/ |