Skip to content

Linting

Linting #5

name: Smart Test Runner
# This workflow intelligently determines which tests to run based on file changes
# Saves CI budget by skipping expensive tests on data-only changes
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main
- develop
jobs:
# First job: Analyze what changed to determine test strategy
analyze-changes:
name: Analyze Changes
runs-on: ubuntu-latest
outputs:
run-frontend-tests: ${{ steps.filter.outputs.frontend }}
run-e2e-tests: ${{ steps.filter.outputs.e2e }}
run-python-tests: ${{ steps.filter.outputs.python }}
run-jekyll-build: ${{ steps.filter.outputs.jekyll }}
is-data-only: ${{ steps.filter.outputs.data-only }}
test-strategy: ${{ steps.strategy.outputs.strategy }}
steps:
- name: 📂 Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Need full history for accurate diff
- name: 📊 Detect file changes
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
# Frontend JavaScript changes requiring tests
frontend:
- 'static/js/**/*.js'
- '!static/js/**/*.min.js'
- 'tests/frontend/**'
- 'package.json'
- 'package-lock.json'
- 'jest.config.js'
# Changes requiring E2E tests
e2e:
- 'static/js/**/*.js'
- '_layouts/**'
- '_includes/**'
- '_pages/**'
- 'tests/e2e/**'
- 'playwright.config.js'
# Python utility changes
python:
- 'utils/**/*.py'
- 'tests/python/**'
- 'pixi.toml'
- 'pyproject.toml'
- 'requirements*.txt'
# Jekyll/Ruby changes
jekyll:
- '_config*.yml'
- '_plugins/**'
- '_layouts/**'
- '_includes/**'
- '_sass/**'
- 'Gemfile*'
# Data-only changes (no tests needed)
data-only:
- '_data/conferences.yml'
- '_data/archive.yml'
- '_data/legacy.yml'
- '_data/types.yml'
- '_i18n/**/*.yml'
- '!**/*.js'
- '!**/*.py'
- '!**/*.rb'
- '!_layouts/**'
- '!_includes/**'
- name: 🎯 Determine test strategy
id: strategy
run: |
# Check if this is a data-only change
if [[ "${{ steps.filter.outputs.data-only }}" == "true" ]] && \
[[ "${{ steps.filter.outputs.frontend }}" == "false" ]] && \
[[ "${{ steps.filter.outputs.e2e }}" == "false" ]] && \
[[ "${{ steps.filter.outputs.python }}" == "false" ]] && \
[[ "${{ steps.filter.outputs.jekyll }}" == "false" ]]; then
echo "strategy=data-validation-only" >> $GITHUB_OUTPUT
echo "📊 Data-only changes detected - will run minimal validation"
elif [[ "${{ steps.filter.outputs.frontend }}" == "true" ]] || \
[[ "${{ steps.filter.outputs.e2e }}" == "true" ]]; then
echo "strategy=full-frontend" >> $GITHUB_OUTPUT
echo "🎭 Frontend changes detected - will run frontend and E2E tests"
elif [[ "${{ steps.filter.outputs.python }}" == "true" ]]; then
echo "strategy=python-only" >> $GITHUB_OUTPUT
echo "🐍 Python changes detected - will run Python tests only"
elif [[ "${{ steps.filter.outputs.jekyll }}" == "true" ]]; then
echo "strategy=jekyll-build" >> $GITHUB_OUTPUT
echo "💎 Jekyll changes detected - will run build test only"
else
echo "strategy=minimal" >> $GITHUB_OUTPUT
echo "✅ Non-critical changes - running minimal checks"
fi
- name: 📝 Comment on PR with test plan
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
with:
script: |
const strategy = '${{ steps.strategy.outputs.strategy }}';
let comment = '## 🧪 Test Strategy Analysis\n\n';
const changes = {
frontend: ${{ steps.filter.outputs.frontend }},
e2e: ${{ steps.filter.outputs.e2e }},
python: ${{ steps.filter.outputs.python }},
jekyll: ${{ steps.filter.outputs.jekyll }},
dataOnly: ${{ steps.filter.outputs.data-only }}
};
comment += '### 📊 Detected Changes:\n';
comment += `- Frontend JS: ${changes.frontend ? '✅ Yes' : '❌ No'}\n`;
comment += `- E2E Required: ${changes.e2e ? '✅ Yes' : '❌ No'}\n`;
comment += `- Python Utils: ${changes.python ? '✅ Yes' : '❌ No'}\n`;
comment += `- Jekyll Config: ${changes.jekyll ? '✅ Yes' : '❌ No'}\n`;
comment += `- Data Only: ${changes.dataOnly ? '✅ Yes' : '❌ No'}\n`;
comment += '\n';
comment += '### 🎯 Test Strategy: `' + strategy + '`\n\n';
switch(strategy) {
case 'data-validation-only':
comment += '✨ **Optimized Run**: Only conference data validation will run.\n';
comment += 'This saves ~15-20 minutes of CI time and reduces costs.\n';
break;
case 'full-frontend':
comment += '🎭 **Full Frontend Testing**: Running unit tests, E2E tests, and visual regression.\n';
break;
case 'python-only':
comment += '🐍 **Python Tests Only**: Running Python utility tests and data validation.\n';
break;
case 'jekyll-build':
comment += '💎 **Jekyll Build Test**: Validating site builds correctly.\n';
break;
default:
comment += '✅ **Minimal Checks**: Running basic validation only.\n';
}
comment += '\n💰 **Cost Savings**: This intelligent test selection reduces unnecessary CI runs.';
// Find and update or create comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('Test Strategy Analysis')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: comment
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}
# Data validation only - for conference data changes
data-validation:
name: Data Validation
needs: analyze-changes
if: always() # Always run data validation
runs-on: ubuntu-latest
steps:
- name: 📂 Checkout repository
uses: actions/checkout@v5
- name: 🐍 Setup Pixi
uses: prefix-dev/setup-pixi@v0.9.0
- name: ✅ Validate conference data
run: |
pixi run sort --check
pixi run validate
- name: 📊 Check for duplicates
run: |
python utils/check_duplicates.py || true
- name: 🔗 Validate URLs (sample)
if: needs.analyze-changes.outputs.is-data-only == 'true'
run: |
# Only check a sample of URLs for data-only changes to save time
python utils/check_links.py --sample 10 || true
# Conditional frontend tests
frontend-tests:
name: Frontend Tests
needs: analyze-changes
if: needs.analyze-changes.outputs.run-frontend-tests == 'true'
uses: ./.github/workflows/frontend-tests.yml

Check failure on line 220 in .github/workflows/smart-test-runner.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/smart-test-runner.yml

Invalid workflow file

error parsing called workflow ".github/workflows/smart-test-runner.yml" -> "./.github/workflows/frontend-tests.yml" (source branch with sha:e83f0958baa8435694a799ca478207bf794f4f3d) : workflow is not reusable as it is missing a `on.workflow_call` trigger
secrets: inherit
# Conditional E2E tests
e2e-tests:
name: E2E Tests
needs: analyze-changes
if: needs.analyze-changes.outputs.run-e2e-tests == 'true'
uses: ./.github/workflows/e2e-tests.yml
secrets: inherit
# Python tests (if utilities changed)
python-tests:
name: Python Tests
needs: analyze-changes
if: needs.analyze-changes.outputs.run-python-tests == 'true'
runs-on: ubuntu-latest
steps:
- name: 📂 Checkout repository
uses: actions/checkout@v5
- name: 🐍 Setup Pixi
uses: prefix-dev/setup-pixi@v0.9.0
- name: 🧪 Run Python tests
run: |
pixi run test
# Jekyll build test
jekyll-build-test:
name: Jekyll Build Test
needs: analyze-changes
if: needs.analyze-changes.outputs.run-jekyll-build == 'true'
runs-on: ubuntu-latest
steps:
- name: 📂 Checkout repository
uses: actions/checkout@v5
- name: 💎 Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
- name: 🏗️ Test Jekyll build
run: |
bundle exec jekyll build
env:
JEKYLL_ENV: test
# Final status check
test-status:
name: Test Status
runs-on: ubuntu-latest
needs: [data-validation, frontend-tests, e2e-tests, python-tests, jekyll-build-test]
if: always()
steps:
- name: ✅ All tests passed
if: |
needs.data-validation.result == 'success' &&
(needs.frontend-tests.result == 'success' || needs.frontend-tests.result == 'skipped') &&
(needs.e2e-tests.result == 'success' || needs.e2e-tests.result == 'skipped') &&
(needs.python-tests.result == 'success' || needs.python-tests.result == 'skipped') &&
(needs.jekyll-build-test.result == 'success' || needs.jekyll-build-test.result == 'skipped')
run: |
echo "✅ All required tests passed!"
echo "Test strategy successfully reduced unnecessary runs."
- name: ❌ Some tests failed
if: |
needs.data-validation.result == 'failure' ||
needs.frontend-tests.result == 'failure' ||
needs.e2e-tests.result == 'failure' ||
needs.python-tests.result == 'failure' ||
needs.jekyll-build-test.result == 'failure'
run: |
echo "❌ Some tests failed. Please check the logs above."
exit 1