Automated triage labeling for GitHub repositories with intelligent label management, release/backport labeling, and stale PR detection.
⚠️ Important: This action uses a two-workflow pattern for fork compatibility. You need to create both workflow files for proper functionality with external contributors.
Create these two workflows in your repository:
.github/workflows/repository-automation-trigger.yml
:
---
name: "Repository Automation: Trigger"
on:
issues:
types: [opened, labeled, unlabeled]
pull_request:
types: [opened, synchronize, edited, ready_for_review, labeled, unlabeled]
permissions:
contents: read
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Create Minimal Metadata
run: |
echo "🚀 Creating minimal metadata for workflow_run event"
mkdir -p ./pr-metadata
if [ "${{ github.event_name }}" == "pull_request" ]; then
TITLE_B64=$(echo -n '${{ github.event.pull_request.title }}' | base64 -w 0)
BODY_B64=$(echo -n '${{ github.event.pull_request.body }}' | base64 -w 0)
cat > ./pr-metadata/metadata.json << EOF
{
"type": "pull_request",
"event_action": "${{ github.event.action }}",
"number": ${{ github.event.pull_request.number }},
"title_base64": "$TITLE_B64",
"body_base64": "$BODY_B64",
"state": "${{ github.event.pull_request.state }}",
"encoding": {"title": "base64", "body": "base64"},
"head": {"ref": "${{ github.event.pull_request.head.ref }}"},
"author": {"login": "${{ github.event.pull_request.user.login }}"}
}
EOF
elif [ "${{ github.event_name }}" == "issues" ]; then
TITLE_B64=$(echo -n '${{ github.event.issue.title }}' | base64 -w 0)
BODY_B64=$(echo -n '${{ github.event.issue.body }}' | base64 -w 0)
cat > ./pr-metadata/metadata.json << EOF
{
"type": "issue",
"event_action": "${{ github.event.action }}",
"number": ${{ github.event.issue.number }},
"title_base64": "$TITLE_B64",
"body_base64": "$BODY_B64",
"state": "${{ github.event.issue.state }}",
"encoding": {"title": "base64", "body": "base64"},
"author": {"login": "${{ github.event.issue.user.login }}"}
}
EOF
fi
- name: Store Metadata as Artifact
uses: actions/upload-artifact@v4
with:
name: pr-metadata
path: pr-metadata/metadata.json
retention-days: 1
.github/workflows/repository-automation.yml
:
---
name: Complete Repository Automation
on:
workflow_run:
workflows: ["Repository Automation: Trigger"]
types: [completed]
permissions:
issues: write
pull-requests: write
checks: write
jobs:
automation:
runs-on: ubuntu-latest
if: github.repository == 'your-org/your-repo' # Update this!
steps:
- name: Repository Automation
uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
custom-github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
For full functionality with all features enabled, update your workflows:
.github/workflows/repository-automation-trigger.yml
(same as basic setup above)
.github/workflows/repository-automation.yml
:
---
name: Complete Repository Automation
on:
# Fork compatibility via workflow_run
workflow_run:
workflows: ["Repository Automation: Trigger"]
types: [completed]
# Scheduled events for stale detection
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
# Manual trigger for testing
workflow_dispatch:
inputs:
pr-number:
description: 'PR number to process (optional)'
required: false
type: string
dry-run:
description: 'Dry run mode (true/false)'
required: false
default: 'false'
permissions:
issues: write
pull-requests: write
checks: write
jobs:
automation:
runs-on: ubuntu-latest
if: github.repository == 'your-org/your-repo' # Update this!
steps:
- name: Repository Automation
uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
custom-github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
dry-run: ${{ github.event.inputs.dry-run || 'false' }}
# Enable all features
accepted-releases: '["2.6", "2.7", "devel"]'
accepted-backports: '["2.5", "2.6", "devel"]'
enable-feature-branch: true
stale-days: 5
All scenarios use the two-workflow pattern shown above. Customize the main workflow by adjusting the action inputs:
Update your repository-automation.yml
to use minimal configuration:
- name: Repository Automation
uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
custom-github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
# No additional features enabled - just triage labeling
Features enabled:
- Adds "triage" label to new issues and PRs
- Protects "triage" label from removal until proper categorization
- Automatically removes "triage" when release labels are applied
Add release/backport configuration to enable YAML parsing:
- name: Repository Automation
uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
custom-github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
accepted-releases: '["1.5", "2.0", "devel"]'
accepted-backports: '["1.4", "1.5"]'
PR description format:
release: "2.0" # Creates "release-2.0" label
backport: "1.5" # Creates "backport-1.5" label
# Multiple versions supported
release: ["2.0", "2.1"] # Creates both labels
Enable feature branch automation:
- name: Repository Automation
uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
custom-github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
enable-feature-branch: true
PR description format:
needs_feature_branch: true # Creates "feature-branch" label
Add stale detection with scheduled triggers:
- name: Repository Automation
uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
custom-github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
stale-days: 7 # Mark PRs stale after 7 days of inactivity
Note: Requires schedule
trigger in your main workflow.
⚠️ Limited Fork Support: This pattern won't work for external contributors from forks.
For simple repositories that don't need fork compatibility:
name: Simple Repository Automation
on:
issues:
types: [opened]
pull_request:
types: [opened, ready_for_review]
permissions:
issues: write
pull-requests: write
jobs:
automation:
runs-on: ubuntu-latest
steps:
- uses: thenets/repo-automation@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Add feature configurations as needed
Name | Description | Required | Default |
---|---|---|---|
github-token |
GitHub token for API access | ✅ | |
custom-github-token |
Custom token for external contributor support | github-token |
|
dry-run |
Preview mode without making changes | false |
|
accepted-releases |
JSON array of accepted release versions | ||
accepted-backports |
JSON array of accepted backport versions | ||
enable-feature-branch |
Enable feature branch automation | false |
|
stale-days |
Days before marking PRs as stale |
Name | Description |
---|---|
labels-added |
JSON array of labels that were added |
actions-taken |
Summary of all actions performed |
features-enabled |
JSON array of features enabled based on inputs |
- Automatically adds "triage" label to new issues and PRs
- Protects triage labels from premature removal
- Smart conditional labeling based on PR state (draft vs ready)
- Removes triage labels when proper categorization is complete
- Parses YAML code blocks in PR descriptions
- Supports single version:
release: "1.5"
- Supports multiple versions:
release: ["1.5", "2.0"]
- Validates against configured accepted versions
- Provides clear error messages for invalid values
- Detects
needs_feature_branch: true
in PR YAML - Automatically applies "feature-branch" label
- Case-insensitive boolean parsing
- Configurable inactivity period
- Considers commits, comments, reviews, and label changes as activity
- Runs on schedule or manual trigger
- Skips already stale PRs
- Two-workflow pattern for external contributor support
- Secure artifact sharing between workflows
- Maintains full functionality for fork PRs
- Requires
CUSTOM_GITHUB_TOKEN
with proper permissions
- Removes "ready for review" labels from closed PRs
- Maintains clean label states
- Nightly cleanup automation
Create these labels in your repository:
triage
- For new issues/PRs requiring categorizationstale
- For inactive PRsready for review
- For PRs ready for team reviewfeature-branch
- For PRs requiring feature branch coordination
🔄 Why Two Workflows? External contributors from forks can't access your repository secrets. The two-workflow pattern solves this by having forks run a simple metadata collection workflow, then the main repository processes that data with full permissions.
For external contributor support, create a fine-grained personal access token with these permissions:
Required Permissions:
- Metadata: Read
- Actions: Read and Write (critical for artifact downloads)
- Code: Read and Write
- Issues: Read and Write
- Pull requests: Read and Write
- Workflows: Read and Write
Setup Instructions:
- Go to GitHub Settings > Personal Access Tokens (Beta)
- Select your repository or choose "All repositories"
- Grant all required permissions above
- Add token as repository secret named
CUSTOM_GITHUB_TOKEN
- Repository Reference: Update
if: github.repository == 'your-org/your-repo'
in your main workflow to match your actual repository - Token Requirement: Without
CUSTOM_GITHUB_TOKEN
, workflows will fail for external contributors with "Resource not accessible" errors - Workflow Names: The trigger workflow name must exactly match the
workflow_run.workflows
reference in your main workflow
This action replaces multiple individual keeper workflows with a single, powerful automation:
Before: 4+ individual workflows (~1,500+ lines) After: 1-2 workflows using this action (~20-80 lines)
See DESIGN.md for detailed migration guidance and technical documentation.
This project is licensed under the MIT License. See the LICENSE file for details.