auto #369
This file contains 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-site-and-compare | |
on: | |
push: | |
branches: | |
tags: | |
paths-ignore: | |
- 'publisher/**' | |
- 'updater/**' | |
- '.github/workflows/ci-build-publisher.yml' | |
- '.github/workflows/ci-build-updater.yml' | |
- '.github/workflows/ci-frontend-check.yml' | |
- '.github/workflows/ci-frontend-lint.yml' | |
- '.github/dependabot.yml' | |
- '.github/FUNDING.yml' | |
- 'hugo/content/**' # content likely won't break the build | |
pull_request: | |
paths-ignore: | |
- 'publisher/**' | |
- 'updater/**' | |
- '.github/workflows/ci-build-publisher.yml' | |
- '.github/workflows/ci-build-updater.yml' | |
- '.github/workflows/ci-frontend-check.yml' | |
- '.github/workflows/ci-frontend-lint.yml' | |
- '.github/dependabot.yml' | |
- '.github/FUNDING.yml' | |
- 'hugo/content/**' # content likely won't break the build | |
jobs: | |
build: | |
name: build-and-compare | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check out code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # Needed to fetch all history for comparison | |
# for prettier as it's unknown how to build css and js without them being minimized | |
- name: Set up Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version: '22.x' | |
cache: 'npm' | |
cache-dependency-path: hugo | |
- name: Set directory names | |
id: set-dirs | |
run: | | |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
echo "old_dir=master" >> $GITHUB_OUTPUT | |
echo "new_dir=pr-${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT | |
else | |
echo "old_dir=old-master" >> $GITHUB_OUTPUT | |
echo "new_dir=new-master" >> $GITHUB_OUTPUT | |
fi | |
- name: Get comparison commit | |
id: get-comparison-commit | |
run: | | |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
echo "compare_sha=$(git rev-parse ${{ github.event.pull_request.base.sha }})" >> $GITHUB_OUTPUT | |
else | |
echo "compare_sha=$(git rev-parse HEAD^1)" >> $GITHUB_OUTPUT | |
fi | |
- name: Build previous version | |
run: | | |
git checkout ${{ steps.get-comparison-commit.outputs.compare_sha }} | |
docker build -t radio-t/site:previous --build-arg DO_NOT_MINIFY=true . | |
# Create directories for previous build | |
mkdir -p ${{ steps.set-dirs.outputs.old_dir }}/hugo | |
cp -r hugo/* ${{ steps.set-dirs.outputs.old_dir }}/hugo/ | |
mkdir -p ${{ steps.set-dirs.outputs.old_dir }}/public | |
# Run the container with proper volume mounts | |
docker run --rm \ | |
-v ${{ github.workspace }}/${{ steps.set-dirs.outputs.old_dir }}/hugo:/srv/hugo \ | |
-v ${{ github.workspace }}/${{ steps.set-dirs.outputs.old_dir }}/public:/srv/hugo/public \ | |
-e DO_NOT_MINIFY_HUGO=true \ | |
radio-t/site:previous | |
# chown everything to the calling user as otherwise it's not possible to change it with sed and prettier later | |
sudo chown -R $USER:$USER ${{ steps.set-dirs.outputs.old_dir }}/public | |
- name: Build current version | |
run: | | |
git checkout ${{ github.event.pull_request.head.sha || github.sha }} | |
docker build -t radio-t/site:current --build-arg DO_NOT_MINIFY=true . | |
# Create directories for current build | |
mkdir -p ${{ steps.set-dirs.outputs.new_dir }}/hugo | |
cp -r hugo/* ${{ steps.set-dirs.outputs.new_dir }}/hugo/ | |
mkdir -p ${{ steps.set-dirs.outputs.new_dir }}/public | |
# Run the container with proper volume mounts | |
docker run --rm \ | |
-v ${{ github.workspace }}/${{ steps.set-dirs.outputs.new_dir }}/hugo:/srv/hugo \ | |
-v ${{ github.workspace }}/${{ steps.set-dirs.outputs.new_dir }}/public:/srv/hugo/public \ | |
-e DO_NOT_MINIFY_HUGO=true \ | |
radio-t/site:current | |
# chown everything to the calling user as otherwise it's not possible to change it with sed and prettier later | |
sudo chown -R $USER:$USER ${{ steps.set-dirs.outputs.new_dir }}/public | |
- name: Install Prettier | |
run: npm install -g prettier | |
- name: Prettify CSS in public directories | |
run: | | |
prettier --write "${{ steps.set-dirs.outputs.old_dir }}/public/**/*.css" | |
prettier --write "${{ steps.set-dirs.outputs.new_dir }}/public/**/*.css" | |
- name: Remove itunes:subtitle from RSS feeds before comparison | |
run: | | |
sed -i 's#<itunes:subtitle>.*</itunes:subtitle>##' ${{ steps.set-dirs.outputs.old_dir }}/public/podcast-archives-short.rss | |
sed -i 's#<itunes:subtitle>.*</itunes:subtitle>##' ${{ steps.set-dirs.outputs.new_dir }}/public/podcast-archives-short.rss | |
sed -i 's#<itunes:subtitle>.*</itunes:subtitle>##' ${{ steps.set-dirs.outputs.old_dir }}/public/podcast-archives.rss | |
sed -i 's#<itunes:subtitle>.*</itunes:subtitle>##' ${{ steps.set-dirs.outputs.new_dir }}/public/podcast-archives.rss | |
- name: Remove hashes from CSS and JS files references | |
run: | | |
find ${{ steps.set-dirs.outputs.old_dir }}/public -type f -exec sed -i 's/\(js\|css\)?id=[^"'\''"]\+/\1/g' {} + | |
find ${{ steps.set-dirs.outputs.new_dir }}/public -type f -exec sed -i 's/\(js\|css\)?id=[^"'\''"]\+/\1/g' {} + | |
- name: Generate diff | |
run: | | |
# Generate initial diff | |
diff -r -N -u ${{ steps.set-dirs.outputs.old_dir }}/public ${{ steps.set-dirs.outputs.new_dir }}/public > temp.diff || true | |
# Process diff file to adjust paths | |
sed -E 's#^(---|\+\+\+) (.+)/public/#\1 \2/#' temp.diff > changes.diff | |
# Store diff size for later use | |
diff_size=$(wc -c < changes.diff) | |
echo "diff_size=$diff_size" >> $GITHUB_ENV | |
# Delete changes.diff if it's empty | |
if [ ! -s changes.diff ]; then | |
rm changes.diff | |
fi | |
# Generate a summary of changed files | |
find ${{ steps.set-dirs.outputs.new_dir }}/public -type f -exec sh -c ' | |
old_dir="${{ steps.set-dirs.outputs.old_dir }}" | |
new_dir="${{ steps.set-dirs.outputs.new_dir }}" | |
file_path=${1#$new_dir/public/} | |
prev_file="$old_dir/public/$file_path" | |
if [ ! -f "$prev_file" ]; then | |
echo "- New: \`$file_path\`" | |
elif ! cmp -s "$1" "$prev_file"; then | |
echo "- Modified: \`$file_path\`" | |
fi | |
' sh {} \; >> changes.md | |
# add line in the beginning of the file only if it's not empty | |
if [ -s changes.md ]; then | |
sed -i '1s/^/Changed files:\n\n/' changes.md | |
fi | |
find ${{ steps.set-dirs.outputs.old_dir }}/public -type f -exec sh -c ' | |
old_dir="${{ steps.set-dirs.outputs.old_dir }}" | |
new_dir="${{ steps.set-dirs.outputs.new_dir }}" | |
file_path=${1#$old_dir/public/} | |
current_file="$new_dir/public/$file_path" | |
if [ ! -f "$current_file" ]; then | |
echo "- Deleted: \`$file_path\`" | |
fi | |
' sh {} \; >> changes.md | |
# delete summary if it's empty | |
if [ ! -s changes.md ]; then | |
rm changes.md | |
fi | |
- name: Create Pastebin Paste with the diff in case it's too large | |
if: github.event_name == 'pull_request' && env.diff_size >= 20000 | |
env: | |
PASTEBIN_API_KEY: ${{ secrets.PASTEBIN_API_KEY }} | |
id: create-pastebin | |
run: | | |
# Use a URL-encoded paste name to handle special characters | |
paste_name=$(echo "radio-t.com Site Changes for PR #${{ github.event.pull_request.number }}, commit ${{ github.sha }}" | jq -sRr @uri) | |
# Post the diff file directly from changes.diff | |
# https://pastebin.com/doc_api | |
paste_output=$(curl --silent "https://pastebin.com/api/api_post.php" \ | |
-d "api_dev_key=$PASTEBIN_API_KEY" \ | |
-d "api_option=paste" \ | |
-d "api_paste_expire_date=1M" \ | |
-d "api_paste_format=diff" \ | |
-d "api_paste_private=0" \ | |
-d "api_paste_name=${paste_name}" \ | |
-d "api_paste_code=$(< changes.diff)" || echo "curl call to pastebin failed") | |
# Check if the output is a valid URL, otherwise print an error | |
if [[ "$paste_output" == "https://"* ]]; then | |
echo "PASTE_URL=$paste_output" >> $GITHUB_ENV | |
else | |
echo "Error: Failed to create Pastebin paste: $paste_output" >&2 | |
fi | |
- name: Upload changes.diff as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: changes.diff | |
path: changes.diff | |
if-no-files-found: ignore | |
- name: Upload changes.md as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: changes.md | |
path: changes.md | |
if-no-files-found: ignore | |
- name: Generate comment body in case there are changes | |
if: env.diff_size != 0 | |
id: get-comment-body | |
run: | | |
SUMMARY=$(cat changes.md) | |
# Truncate SUMMARY if it exceeds 20,000 characters | |
if [ ${#SUMMARY} -gt 20000 ]; then | |
SUMMARY="${SUMMARY:0:20000}... (truncated)" | |
fi | |
echo "body<<EOF" >> $GITHUB_OUTPUT | |
echo "### Site Build Comparison" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
echo "**Build completed at:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
echo "\`\`\`" >> $GITHUB_OUTPUT | |
echo "$SUMMARY" >> $GITHUB_OUTPUT | |
echo "\`\`\`" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
# If diff is small enough (<20KB), include it directly under spoiler | |
if [ "$diff_size" -lt 20000 ]; then | |
echo "**Full changes:**" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
echo "<details>" >> $GITHUB_OUTPUT | |
echo "<summary>Click to expand diff</summary>" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
echo "\`\`\`diff" >> $GITHUB_OUTPUT | |
cat changes.diff >> $GITHUB_OUTPUT | |
echo "\`\`\`" >> $GITHUB_OUTPUT | |
echo "</details>" >> $GITHUB_OUTPUT | |
fi | |
echo "" >> $GITHUB_OUTPUT | |
echo "[View full changes diff](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})" >> $GITHUB_OUTPUT | |
if [ -n "$PASTE_URL" ]; then | |
echo "[View diff on Pastebin]($PASTE_URL)" >> $GITHUB_OUTPUT | |
fi | |
echo "EOF" >> $GITHUB_OUTPUT | |
- name: Generate comment body in case there are no changes | |
if: env.diff_size == 0 | |
id: get-comment-body-no-changes | |
run: | | |
echo "body<<EOF" >> $GITHUB_OUTPUT | |
echo "### Site Build Comparison" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
echo "**Build completed at:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_OUTPUT | |
echo "" >> $GITHUB_OUTPUT | |
echo "No changes detected." >> $GITHUB_OUTPUT | |
echo "EOF" >> $GITHUB_OUTPUT | |
- name: Find existing comment | |
id: find-comment | |
if: github.event_name == 'pull_request' | |
uses: peter-evans/find-comment@v3 | |
with: | |
issue-number: ${{ github.event.pull_request.number }} | |
body-includes: "### Site Build Comparison" | |
- name: Create or update comment | |
if: github.event_name == 'pull_request' | |
uses: peter-evans/create-or-update-comment@v4 | |
continue-on-error: true | |
with: | |
comment-id: ${{ steps.find-comment.outputs.comment-id }} | |
issue-number: ${{ github.event.pull_request.number }} | |
body: ${{ steps.get-comment-body.outputs.body }}${{ steps.get-comment-body-no-changes.outputs.body }} | |
edit-mode: replace |