Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions .github/workflows/dependency-review-action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Automatically scans every PR for newly added dependencies
# Blocks merges if a dependency license is NOT in the allow-list
# Flags CVEs with moderate+ severity
# Docs: https://github.com/actions/dependency-review-action


name: Dependency Review

on:
pull_request:
branches:
- main
- master
- develop
# Only re-run when dependency manifests actually change
paths:
# JavaScript / TypeScript / Node
- "**/package.json"
- "**/package-lock.json"
- "**/yarn.lock"
- "**/pnpm-lock.yaml"
# Python
- "**/requirements*.txt"
- "**/Pipfile.lock"
- "**/pyproject.toml"
- "**/poetry.lock"
# Rust
- "**/Cargo.toml"
- "**/Cargo.lock"
# Go
- "**/go.mod"
- "**/go.sum"
# Java / Kotlin / Android
- "**/pom.xml"
- "**/build.gradle"
- "**/build.gradle.kts"
- "**/*.gradle"
# Ruby
- "**/Gemfile.lock"
# Docker / Infrastructure
- "**/Dockerfile"
- "**/docker-compose*.yml"
- "**/docker-compose*.yaml"
# GitHub Actions themselves
- ".github/workflows/*.yml"
- ".github/workflows/*.yaml"

permissions:
contents: read # Required to read the repo content
# pull-requests: write # Required to post review comments on the PR

jobs:
dependency-review:
name: Dependency & License Review
runs-on: ubuntu-latest

steps:
- name: Run Dependency Review
uses: actions/dependency-review-action@v4
with:
# ── VULNERABILITY SETTINGS ──────────────────────────
# Fail if any newly added dependency has a CVE at this
# severity level or above. Options: low | moderate | high | critical
fail-on-severity: moderate

# Which dependency scopes to check for vulnerabilities
# Options: runtime | development | unknown (comma-separated)
fail-on-scopes: runtime

# ── LICENSE ENFORCEMENT ─────────────────────────────
# ALLOW: Only these licenses are permitted in new dependencies.
# PRs introducing any other license will fail automatically.
# Full SPDX list: https://spdx.org/licenses/
allow-licenses: >-
MIT,
Apache-2.0,
BSD-2-Clause,
BSD-3-Clause,
ISC,
CC0-1.0,
Unlicense,
GPL-2.0-only,
GPL-2.0-or-later,
GPL-3.0-only,
GPL-3.0-or-later,
LGPL-2.0-only,
LGPL-2.0-or-later,
LGPL-2.1-only,
LGPL-2.1-or-later,
LGPL-3.0-only,
LGPL-3.0-or-later,
AGPL-3.0-only,
AGPL-3.0-or-later,
MPL-2.0,
EUPL-1.2,
Python-2.0,
PSF-2.0

# PER-PACKAGE EXCEPTIONS: Packages excluded from license checks entirely.
# Use for packages with unrecognized/non-standard license declarations.
# Format: "pkg:npm/name, pkg:pypi/name, pkg:githubactions/owner/repo@version"
# ── Edit this list when adding approved exceptions ──
# allow-dependencies-licenses: >-
# pkg:npm/example-package,
# pkg:pypi/example-package

# ── SCOPE FILTERING ─────────────────────────────────
# Skip dev-only dependencies (test frameworks, linters, etc.)
# They are not shipped to production so risk is lower.
# Set to "all" to also scan devDependencies.
# Options: runtime | development | all
# Using "runtime" keeps noise low in template repos
# where dev deps vary wildly by project type.
# Uncomment the line below to enforce on devDeps too:
# fail-on-scopes: runtime, development
allow-ghsas: "" # Leave empty to block all known GHSAs

# ── OUTPUT & COMMENTS ────────────────────────────────
# Post a detailed summary comment directly on the PR
# comment-summary-in-pr: always

# Fail (don't just warn) on license violations.
# Change to "true" to only warn without failing.
warn-only: false

# ── VULNERABILITY DATABASE ───────────────────────────
# Use the GitHub Advisory Database (GHSA) as the source.
# This is the default; listed explicitly for clarity.
# vulnerability-check: true # default
# Add explicitly so teams know it's active
show-openssf-scorecard: true
warn-on-openssf-scorecard-level: 3

# Post a status summary badge to PR
# summarize:
# name: Post Review Summary
# runs-on: ubuntu-latest
# needs: dependency-review
# if: always()

# steps:
# - name: 📋 Summarize Result
# run: |
# if [ "${{ needs.dependency-review.result }}" == "success" ]; then
# echo "✅ Dependency review passed — no license violations or CVEs found."
# else
# echo "❌ Dependency review failed — check the PR comment for details."
# echo ""
# echo "Common fixes:"
# echo " • Replace dependencies using licenses not in allow-licenses"
# echo " • Upgrade vulnerable packages to patched versions"
# echo " • Add an explicit exception to allow-dependencies-licenses if intentional"
# fi
Empty file.
210 changes: 210 additions & 0 deletions .github/workflows/setup-labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
name: Setup Repository Labels

on:
workflow_dispatch: # Manual trigger
push:
branches: [main, master]
paths:
- '.github/workflows/setup-labels.yml'

permissions:
issues: write

jobs:
create-labels:
runs-on: ubuntu-latest
steps:
- name: Create all required labels
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// Define all labels with colors and descriptions
const requiredLabels = [
// ==================== CONTRIBUTOR LABELS ====================
{
name: 'org-member',
color: '0E8A16',
description: 'Member of the organization with admin/maintain permissions'
},
{
name: 'first-time-contributor',
color: '7057FF',
description: 'First PR of an external contributor'
},
{
name: 'repeat-contributor',
color: '6F42C1',
description: 'PR from an external contributor who already had PRs merged'
},

// ==================== ISSUE TRACKING LABELS ====================
{
name: 'no-issue-linked',
color: 'D73A4A',
description: 'PR is not linked to any issue'
},

// ==================== FILE TYPE LABELS ====================
{
name: 'documentation',
color: '0075CA',
description: 'Changes to documentation files'
},
{
name: 'frontend',
color: 'FEF2C0',
description: 'Changes to frontend code'
},
{
name: 'backend',
color: 'BFD4F2',
description: 'Changes to backend code'
},
{
name: 'javascript',
color: 'F1E05A',
description: 'JavaScript/TypeScript code changes'
},
{
name: 'python',
color: '3572A5',
description: 'Python code changes'
},
{
name: 'configuration',
color: 'EDEDED',
description: 'Configuration file changes'
},
{
name: 'github-actions',
color: '2088FF',
description: 'GitHub Actions workflow changes'
},
{
name: 'dependencies',
color: '0366D6',
description: 'Dependency file changes'
},
{
name: 'tests',
color: 'C5DEF5',
description: 'Test file changes'
},
{
name: 'docker',
color: '0DB7ED',
description: 'Docker-related changes'
},
{
name: 'ci-cd',
color: '6E5494',
description: 'CI/CD pipeline changes'
},

// ==================== SIZE LABELS ====================
{
name: 'size/XS',
color: '00FF00',
description: 'Extra small PR (≤10 lines changed)'
},
{
name: 'size/S',
color: '77FF00',
description: 'Small PR (11-50 lines changed)'
},
{
name: 'size/M',
color: 'FFFF00',
description: 'Medium PR (51-200 lines changed)'
},
{
name: 'size/L',
color: 'FF9900',
description: 'Large PR (201-500 lines changed)'
},
{
name: 'size/XL',
color: 'FF0000',
description: 'Extra large PR (>500 lines changed)'
}
];

console.log('='.repeat(60));
console.log('🏷️ REPOSITORY LABEL SETUP');
console.log('='.repeat(60));
console.log(`Total labels to create: ${requiredLabels.length}\n`);

// Get existing labels with pagination
const existingLabels = await github.paginate(
github.rest.issues.listLabelsForRepo,
{
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
}
);

const existingLabelNames = existingLabels.map(label => label.name);

let created = 0;
let updated = 0;
let skipped = 0;
let failed = 0;

// Process each label
for (const label of requiredLabels) {
try {
if (!existingLabelNames.includes(label.name)) {
// Create new label
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label.name,
color: label.color,
description: label.description
});
console.log(`✅ Created: ${label.name} (#${label.color})`);
created++;
} else {
// Update existing label (in case color/description changed)
const existingLabel = existingLabels.find(l => l.name === label.name);
if (existingLabel.color !== label.color || existingLabel.description !== label.description) {
await github.rest.issues.updateLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label.name,
color: label.color,
description: label.description
});
console.log(`🔄 Updated: ${label.name} (#${label.color})`);
updated++;
} else {
console.log(`⏭️ Skipped: ${label.name} (already exists)`);
skipped++;
}
}
} catch (error) {
console.log(`❌ Failed: ${label.name} - ${error.message}`);
failed++;
}
}

// Summary
console.log('\n' + '='.repeat(60));
console.log('📊 SUMMARY');
console.log('='.repeat(60));
console.log(`✅ Created: ${created}`);
console.log(`🔄 Updated: ${updated}`);
console.log(`⏭️ Skipped: ${skipped}`);
console.log(`❌ Failed: ${failed}`);
console.log('='.repeat(60));

// Fail the step if any labels failed to create/update
if (failed > 0) {
core.setFailed(`Label setup failed! ${failed} label(s) could not be created or updated.`);
} else if (created > 0 || updated > 0) {
console.log('\n🎉 Label setup complete! Your repository is ready.');
} else {
console.log('\n✨ All labels are already up to date.');
}
Loading
Loading