CI workflow (lockfale/OSINT-Framework)
The CI workflow from lockfale/OSINT-Framework, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the lockfale/OSINT-Framework repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
schedule:
# Run link check weekly on Saturday at 08:00 UTC
- cron: '0 8 * * 6'
jobs:
json-lint:
name: JSON Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate arf.json is well-formed
run: python3 -m json.tool public/arf.json > /dev/null
smoke-test:
name: Smoke Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check index.html local asset references exist
run: |
check_asset() {
local path="public/$1"
if [ ! -f "$path" ]; then
echo "MISSING: $path"
exit 1
else
echo "OK: $path"
fi
}
check_asset "css/arf.css"
check_asset "js/d3.min.js"
check_asset "js/arf.js"
check_asset "arf.json"
link-check:
name: Link Check
runs-on: ubuntu-latest
# Only run on schedule (weekly Saturday) - avoid hammering external sites on every push/PR
if: github.event_name == 'schedule'
steps:
- uses: actions/checkout@v4
- name: Extract URLs from arf.json
run: |
python3 -c "
import json, re, sys
with open('public/arf.json') as f:
data = json.load(f)
def extract_urls(node):
urls = []
url = node.get('url', '')
if url and url.startswith('http'):
urls.append(url)
for child in node.get('children', []):
urls.extend(extract_urls(child))
return urls
urls = extract_urls(data)
print(f'Found {len(urls)} URLs', file=sys.stderr)
with open('urls.txt', 'w') as f:
f.write('\n'.join(urls))
"
- name: Run lychee link checker
uses: lycheeverse/lychee-action@v2
with:
args: |
--verbose
--no-progress
--timeout 20
--max-retries 2
--retry-wait-time 5
--accept 200,201,204,206,301,302,307,308,403,429
urls.txt
fail: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: CI on: push: branches: [master] pull_request: branches: [master] schedule: # Run link check weekly on Saturday at 08:00 UTC - cron: '0 8 * * 6' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: json-lint: timeout-minutes: 30 name: JSON Lint runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Validate arf.json is well-formed run: python3 -m json.tool public/arf.json > /dev/null smoke-test: timeout-minutes: 30 name: Smoke Test runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Check index.html local asset references exist run: | check_asset() { local path="public/$1" if [ ! -f "$path" ]; then echo "MISSING: $path" exit 1 else echo "OK: $path" fi } check_asset "css/arf.css" check_asset "js/d3.min.js" check_asset "js/arf.js" check_asset "arf.json" link-check: timeout-minutes: 30 name: Link Check runs-on: latchkey-small # Only run on schedule (weekly Saturday) - avoid hammering external sites on every push/PR if: github.event_name == 'schedule' steps: - uses: actions/checkout@v4 - name: Extract URLs from arf.json run: | python3 -c " import json, re, sys with open('public/arf.json') as f: data = json.load(f) def extract_urls(node): urls = [] url = node.get('url', '') if url and url.startswith('http'): urls.append(url) for child in node.get('children', []): urls.extend(extract_urls(child)) return urls urls = extract_urls(data) print(f'Found {len(urls)} URLs', file=sys.stderr) with open('urls.txt', 'w') as f: f.write('\n'.join(urls)) " - name: Run lychee link checker uses: lycheeverse/lychee-action@v2 with: args: | --verbose --no-progress --timeout 20 --max-retries 2 --retry-wait-time 5 --accept 200,201,204,206,301,302,307,308,403,429 urls.txt fail: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.