Skip to content

broken-links

broken-links #5

Workflow file for this run

name: broken-links
on:
schedule:
# Nightly at 09:00 UTC (around 03:00 MT / 04:00 CT).
- cron: '0 9 * * *'
workflow_dispatch: {}
permissions:
issues: write
contents: read
jobs:
crawl:
name: Crawl site for broken links
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Pick target URL
id: target
# Default to the current preview host (beta.ontargetaba.com on
# the OnTargetDevs CF Pages project). Override via the STAGING_URL
# secret if a different host should be crawled.
run: |
if [ -n "${{ secrets.STAGING_URL }}" ]; then
echo "url=${{ secrets.STAGING_URL }}" >> "$GITHUB_OUTPUT"
else
echo "url=https://beta.ontargetaba.com/" >> "$GITHUB_OUTPUT"
fi
- name: Run Lychee
id: lychee
uses: lycheeverse/lychee-action@v2
with:
args: >-
--verbose
--no-progress
--max-retries 2
--retry-wait-time 5
--timeout 20
--accept 200,206,429
--include-verbatim
--max-recursion-depth 3
--exclude '^https://ontargetaba\.com/'
--exclude '^https://static\.hotjar\.com/c/hotjar-$'
--exclude 'search_term_string'
--exclude '^https://(www\.)?linkedin\.com/'
--exclude '^https://(www\.)?instagram\.com/'
--exclude '^https://(www\.)?facebook\.com/'
${{ steps.target.outputs.url }}
fail: false
output: ./lychee-report.md
- name: Find existing tracking issue
id: existing
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
num=$(gh issue list --state open --label broken-links \
--search "Broken links found" \
--json number --jq '.[0].number // empty')
echo "number=$num" >> "$GITHUB_OUTPUT"
- name: Open or update tracking issue
if: steps.lychee.outputs.exit_code != '0'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET_URL: ${{ steps.target.outputs.url }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
date_str=$(date -u +%Y-%m-%d)
title="Broken links found ${date_str}"
# Build the body in a file. We previously stitched it with
# bash $(...) + +=, but command substitution strips trailing
# newlines, so when lychee-report.md didn't end with one the
# closing ``` ended up smushed against the last content line.
# Writing through printf to a real file gives us deterministic
# line endings — closing fence is always on its own line.
{
printf '## Broken links\n\n'
printf 'Target: %s\n' "$TARGET_URL"
printf 'Run: %s\n\n' "$RUN_URL"
printf '```\n'
if [ -s ./lychee-report.md ]; then
cat ./lychee-report.md
else
printf 'See run logs for details.\n'
fi
# Force a final newline before the closing fence regardless
# of whether the report ended with one.
printf '\n```\n'
} > /tmp/issue-body.md
if [ -n "${{ steps.existing.outputs.number }}" ]; then
gh issue edit "${{ steps.existing.outputs.number }}" \
--title "$title" \
--body-file /tmp/issue-body.md
else
gh issue create \
--title "$title" \
--body-file /tmp/issue-body.md \
--label broken-links
fi
- name: Close tracking issue when clean
if: steps.lychee.outputs.exit_code == '0' && steps.existing.outputs.number != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh issue close "${{ steps.existing.outputs.number }}" \
--comment "All previously broken links are now resolving. Closing."