Skip to content

Fix deploy and HTML diff false positive #502

Fix deploy and HTML diff false positive

Fix deploy and HTML diff false positive #502

Workflow file for this run

name: Diff HTML
on:
pull_request:
types:
# Defaults
- opened
- synchronize
- reopened
# Additional
- closed
env:
BRANCH_NAME_HTML_OLD: __diff__html_old
COLLAPSE_GT_LINES: 10
DIFF_CONTEXT: 5
GIT_IGNORE: |
.doctrees/
__pycache__/
PRETTIER_GLOB: "**/*.{js,css,html,xml}"
PYTHON_VERSION: "3.10"
ROOT_DIR_DIFF: ./docs/_build/html
TRUNCATE_TO_BYTES: 256000
jobs:
build:
name: Build HTML
if: github.event.action != 'closed' || (github.event.pull_request.merged && github.event.pull_request.base.ref == 'main')
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Initialize Python and Poetry
uses: ./.github/actions/init
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Build docs
env:
SPHINX_GITHUB_BRANCH: main
SPHINX_HTML_BASEURL: "https://rob86stage.robpol86.com/"
run: make docs
- name: Create .gitignore
run: printenv GIT_IGNORE |tee -a "$ROOT_DIR_DIFF/.gitignore"
- name: Prettify
run: |
PS4="\n\033[1;33m$PS4\033[0m"
set -euxo pipefail
npm install -g prettier @prettier/plugin-xml
prettier --write "$ROOT_DIR_DIFF/$PRETTIER_GLOB"
- name: Store HTML as temporary artifact
if: github.event.action != 'closed'
uses: actions/upload-artifact@v3
with:
name: html_new
if-no-files-found: error
path: "${{ env.ROOT_DIR_DIFF }}"
- name: Store HTML in orphaned branch
if: github.event.pull_request.merged && github.event.pull_request.base.ref == 'main'
uses: peaceiris/actions-gh-pages@v3
with:
commit_message: "[skip ci]"
enable_jekyll: true # Don't create .nojekyll
force_orphan: true # Discard git history
github_token: "${{ secrets.GITHUB_TOKEN }}"
publish_branch: "${{ env.BRANCH_NAME_HTML_OLD }}"
publish_dir: "${{ env.ROOT_DIR_DIFF }}"
diff:
name: Diff
if: github.event.action != 'closed'
runs-on: ubuntu-latest
needs: build
steps:
- name: Fetch old HTML
uses: actions/checkout@v3
with:
ref: "${{ env.BRANCH_NAME_HTML_OLD }}"
path: html
- name: Prepare for new HTML
run: git -C html rm -r . && git -C html restore --staged .
- name: Fetch new HTML
uses: actions/download-artifact@v3
with:
name: html_new
path: html
- name: Git Status
id: git_status
run: |
git -C html add .
git -C html status --porcelain |tee git_status.txt
if [ -s git_status.txt ]; then
echo "changed=true" >> $GITHUB_OUTPUT
else
echo "no-changes=true" >> $GITHUB_OUTPUT
rm -v git_status.txt
fi
- name: Git Diff
id: git_diff
if: hashFiles('git_status.txt')
run: |
git -C html diff --diff-filter=M --unified="$DIFF_CONTEXT" HEAD |grep -Pv "^(diff|index) " |tee git_diff.patch
if [ -s git_diff.patch ]; then
echo "modified=true" >> $GITHUB_OUTPUT
else
echo "no-modifications=true" >> $GITHUB_OUTPUT
rm -v git_diff.patch
fi
- name: Truncate
if: hashFiles('git_diff.patch')
run: |
cp git_diff.patch git_diff.patch.orig
head --bytes="$TRUNCATE_TO_BYTES" git_diff.patch.orig > git_diff.patch
if ! cmp -s git_diff.patch git_diff.patch.orig; then
echo -e "\n\nTruncated" |tee -a git_diff.patch
tail --bytes=+"$(( TRUNCATE_TO_BYTES + 1 ))" git_diff.patch.orig > git_diff.patch.truncated
fi
rm -v git_diff.patch.orig
- name: Store text/patch files as temporary artifacts
if: hashFiles('git_status.txt')
uses: actions/upload-artifact@v3
with:
name: git_status_diff
path: |
git_status.txt
git_diff.patch
git_diff.patch.truncated
outputs:
changed: "${{ steps.git_status.outputs.changed }}"
no-changes: "${{ steps.git_status.outputs.no-changes }}"
modified: "${{ steps.git_diff.outputs.modified }}"
no-modifications: "${{ steps.git_diff.outputs.no-modifications }}"
post:
name: Post
if: github.event.action != 'closed'
runs-on: ubuntu-latest
needs: diff
env:
HEADER_PREFIX: "Diff Against [Old HTML]"
HEADER_URL_BASE: "https://github.com/${{ github.repository }}/tree"
steps:
- name: Fetch text/patch files
if: needs.diff.outputs.changed
uses: actions/download-artifact@v3
with:
name: git_status_diff
- name: Split patch
if: hashFiles('git_diff.patch')
run: |
PS4="\n\033[1;33m$PS4\033[0m"
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y rename splitpatch
splitpatch git_diff.patch
rm -v git_diff.patch
rename 's/.patch.(\d{3})$/.$1.patch/' *.patch.???
ls -lah
- name: Post (no changes)
if: needs.diff.outputs.no-changes
uses: actions/github-script@v6
with:
script: |
const url = `${process.env.HEADER_URL_BASE}/${process.env.BRANCH_NAME_HTML_OLD}`
const header = `${process.env.HEADER_PREFIX}(${url})`
const body = `*No HTML changes detected.*`
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `### ${header}\n\n${body}`
})
- name: Post (no modified)
if: needs.diff.outputs.changed && needs.diff.outputs.no-modifications
uses: actions/github-script@v6
with:
script: |
const url = `${process.env.HEADER_URL_BASE}/${process.env.BRANCH_NAME_HTML_OLD}`
const header = `${process.env.HEADER_PREFIX}(${url})`
const fs = require(`fs`)
const gitStatus = fs.readFileSync(`git_status.txt`, {encoding:`utf8`, flag:`r`}).trimEnd()
const body = `\`\`\`\n${gitStatus}\n\`\`\`\n`
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `### ${header}\n\n${body}`
})
- name: Post Diff
if: needs.diff.outputs.changed && needs.diff.outputs.modified
uses: actions/github-script@v6
env:
IS_TRUNCATED: "${{ hashFiles('git_diff.patch.truncated') }}"
with:
script: |
const fs = require(`fs`)
function genHeader() {
const url = `${process.env.HEADER_URL_BASE}/${process.env.BRANCH_NAME_HTML_OLD}`
var header = `${process.env.HEADER_PREFIX}(${url})`
if (process.env.IS_TRUNCATED) {
var size = fs.statSync(`git_diff.patch.truncated`).size
header += ` (${size} Byte${size == 1 ? '' : 's'} Truncated)`
}
return header
}
function* yieldFileContents(dir, suffix) {
const files = fs.readdirSync(dir).filter(fileName => fileName.endsWith(suffix))
for (const fileName of files) {
const contents = fs.readFileSync(fileName, {encoding:`utf8`, flag:`r`})
yield {fileName: fileName.slice(0, -suffix.length), contents: contents}
}
}
function collapse(fileName, contents) {
var numLines = contents.match(/^/mg).length
if (numLines > parseInt(process.env.COLLAPSE_GT_LINES))
return `<details>\n<summary>Show ${numLines} lines from ${fileName}</summary>\n\n${contents}\n</details>`
return contents
}
// git status
const gitStatus = fs.readFileSync(`git_status.txt`, {encoding:`utf8`, flag:`r`})
var body = collapse(`git_status.txt`, `\`\`\`\n${gitStatus.trimEnd()}\n\`\`\``)
// git diff
for (const {fileName, contents} of yieldFileContents(`./`, `.patch`)) {
body += `\n\n` + collapse(fileName, `\`\`\`diff\n${contents.trimEnd()}\n\`\`\``)
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `### ${genHeader()}\n\n${body}`
})