Skip to content

Add Outlines to the list of community providers #242

Add Outlines to the list of community providers

Add Outlines to the list of community providers #242

Workflow file for this run

name: Check PR size
on:
pull_request_target:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to check (optional)'
required: false
type: string
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
size:
runs-on: ubuntu-latest
steps:
- name: Get PR data for manual trigger
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number
id: get_pr
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const { data } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ github.event.inputs.pr_number }}
});
return JSON.stringify(data);
- name: Evaluate PR size
if: github.event_name == 'pull_request_target' || (github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number)
uses: actions/github-script@v7
env:
PR_JSON: ${{ steps.get_pr.outputs.result }}
with:
script: |
const pr = context.payload.pull_request || JSON.parse(process.env.PR_JSON || '{}');
if (!pr || !pr.number) {
core.setFailed('Unable to resolve PR data. For workflow_dispatch, pass a valid pr_number.');
return;
}
// Check for draft PRs and bots
const isDraft = !!pr.draft;
const login = pr.user.login;
const isBot = pr.user.type === 'Bot' || /\[bot\]$/.test(login);
if (isDraft || isBot) {
core.info('Draft or bot PR – skipping size enforcement');
return;
}
const totalChanges = pr.additions + pr.deletions;
core.info(`PR contains ${pr.additions} additions and ${pr.deletions} deletions (${totalChanges} total)`);
const sizeLabel =
totalChanges < 50 ? 'size/XS' :
totalChanges < 150 ? 'size/S' :
totalChanges < 600 ? 'size/M' :
totalChanges < 1000 ? 'size/L' : 'size/XL';
// Re-fetch labels to avoid acting on stale payload data
const { data: freshIssue } = await github.rest.issues.get({
...context.repo,
issue_number: pr.number
});
const currentLabels = (freshIssue.labels || []).map(l => l.name);
// Remove old size labels before adding new one
const allSizeLabels = ['size/XS', 'size/S', 'size/M', 'size/L', 'size/XL'];
const toRemove = currentLabels.filter(name => allSizeLabels.includes(name) && name !== sizeLabel);
for (const name of toRemove) {
try {
await github.rest.issues.removeLabel({
...context.repo,
issue_number: pr.number,
name
});
} catch (_) {
// Ignore if already removed
}
}
await github.rest.issues.addLabels({
...context.repo,
issue_number: pr.number,
labels: [sizeLabel]
});
// Check if PR author is a maintainer
let authorPerm = 'none';
try {
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: pr.user.login,
});
authorPerm = data.permission || 'none';
} catch (_) {
// User might not have any permissions
}
core.info(`Author permission: ${authorPerm}`);
const isMaintainer = ['admin', 'maintain'].includes(authorPerm); // Stricter maintainer definition
// Check for bypass label (using fresh labels)
const hasBypass = currentLabels.includes('bypass:size-limit');
const MAX_LINES = 1000;
if (totalChanges > MAX_LINES) {
if (isMaintainer || hasBypass) {
core.info(`${isMaintainer ? 'Maintainer' : 'Bypass label'} - allowing large PR with ${totalChanges} lines`);
} else {
core.setFailed(
`This PR contains ${totalChanges} lines of changes, which exceeds the maximum of ${MAX_LINES} lines. ` +
`Please split this into smaller, focused pull requests.`
);
}
}