A GitHub App to automate the enforcement of organizational policies and security best practices across all repositories within a GitHub organization.
- About The Project
- Features
- Tech Stack
- Getting Started
- Configuration
- Testing
- Dependency Management
- Documentation
- Production Deployment
- Project Scope
- License
The 10x GitHub Policy Enforcer is a GitHub App with an accompanying web UI designed to automate the enforcement of organizational policies and security best practices across all repositories within a GitHub organization.
It uses a flexible policy evaluation engine to scan repositories for compliance with a centrally managed configuration file. When violations are found, it can automatically perform actions like creating issues in the repository or archiving it. The web dashboard provides a clear overview of your organization's compliance posture.
The application uses a dual-authentication strategy:
- GitHub App: For backend services to perform automated scans and actions
- GitHub OAuth App: For user authentication to the web dashboard
- Automated Scans: Performs daily (via scheduled jobs) and on-demand scans of all active repositories.
- Centralized Configuration: All policies are defined in a single
.github/config.yamlfile for easy management. - Extensible Policy Engine: The application uses a strategy pattern to make it easy to add new policy evaluators.
- Automated Actions: Creates issues or archives repositories that violate policies with duplicate prevention and comprehensive action logging.
- Compliance Dashboard: A Blazor-based web UI to view non-compliant repositories, violation details, and overall compliance metrics.
- Background Job Processing: Uses Hangfire for reliable background processing of scans and actions, ensuring the UI remains responsive.
- Action Logging: All automated actions are logged to the database with status tracking and detailed information.
- API Documentation: Provides Swagger/OpenAPI documentation for any exposed API endpoints.
| Category | Technology |
|---|---|
| Backend | ASP.NET Core (.NET 8) |
| Frontend | Blazor Server with Microsoft Fluent UI |
| Database | Azure SQL Database (or local SQL Server) |
| Background Jobs | Hangfire |
| API Docs | Swagger / OpenAPI |
| Hosting | Azure App Service |
| GitHub API | Octokit.net |
| Testing | xUnit, bUnit, NSubstitute, WireMock.Net, Testcontainers, NJsonSchema, Verify.NET, Playwright |
| CI/CD | GitHub Actions |
To get a local copy up and running, follow these simple steps.
- Clone the repo:
git clone https://github.com/your_username/10xGitHubPolicies.git
- Navigate to the project root directory:
cd 10xGitHubPolicies - Start the local SQL Server database:
docker-compose up -d
- Navigate to the application directory:
cd 10xGitHubPolicies.App - Install dependencies:
dotnet restore
- Apply database migrations:
dotnet ef database update
- Trust the HTTPS development certificate:
dotnet dev-certs https --trust
- Run the application with HTTPS profile:
dotnet run --launch-profile https
Alternatively, you can run the project from the root directory:
dotnet run --project 10xGitHubPolicies.App/10xGitHubPolicies.App.csproj --launch-profile httpsThe application will be available at:
- HTTPS:
https://localhost:7040(primary) - HTTP:
http://localhost:5222(redirects to HTTPS)
| URL | Description | Authentication Required |
|---|---|---|
/ |
Main dashboard - compliance overview and repository scanning | ✅ Yes |
/login |
GitHub OAuth login page | ❌ No (public) |
/logout |
User logout and session cleanup | ❌ No (public) |
/access-denied |
Access denied page for unauthorized users | ❌ No (public) |
/onboarding |
First-time setup wizard for configuration | ❌ No (public) |
/debug |
Debug information and authentication details | ✅ Yes |
/hangfire |
Background job dashboard and monitoring | ✅ Yes |
/challenge |
OAuth challenge endpoint for authentication flow | ❌ No (public) |
/signin-github |
GitHub OAuth callback endpoint | ❌ No (public) |
The application is configured via appsettings.json and user secrets for sensitive data.
Test Mode is a special application mode designed for E2E testing and development scenarios. When enabled, it bypasses user authentication and authorization checks, allowing automated testing without requiring real GitHub OAuth tokens or team membership verification.
- Authentication Bypass: Automatically authenticates users as a fake
mackowskiuser - Authorization Bypass: Skips team membership verification (always returns
true) - GitHub App Services: Remain fully functional for repository operations
- No Real Tokens: Eliminates the need for actual GitHub Personal Access Tokens
Via Configuration File (Recommended for development):
-
Edit
appsettings.Development.json:{ "TestMode": { "Enabled": true } } -
Restart the application:
dotnet run --launch-profile https
Via Environment Variable (Useful for CI/CD):
export TestMode__Enabled=true
dotnet run --launch-profile httpsVia Command Line (Temporary override):
dotnet run --launch-profile https --TestMode:Enabled=trueVia Configuration File:
-
Edit
appsettings.Development.json:{ "TestMode": { "Enabled": false } } -
Restart the application
Via Environment Variable:
export TestMode__Enabled=false
dotnet run --launch-profile https| Option | Type | Default | Description |
|---|---|---|---|
TestMode:Enabled |
bool |
false |
Enables/disables test mode authentication bypass |
- E2E Testing: Automated browser tests that need to bypass authentication
- Development: Local development without GitHub OAuth setup
- CI/CD: Automated testing pipelines
- Demo Environments: Quick demonstrations without authentication setup
The application uses a dual-authentication strategy requiring both a GitHub App (for backend services) and a GitHub OAuth App (for user authentication).
The GitHub App is used by backend services to perform automated scans and actions against the GitHub API.
-
Initialize user secrets for the project (if you haven't already):
cd 10xGitHubPolicies.App dotnet user-secrets init -
Set the GitHub App secrets. Replace the placeholder values with your App's credentials:
dotnet user-secrets set "GitHubApp:AppId" "YOUR_GITHUB_APP_ID" dotnet user-secrets set "GitHubApp:InstallationId" "YOUR_GITHUB_APP_INSTALLATION_ID" dotnet user-secrets set "GitHubApp:PrivateKey" "PASTE_YOUR_PRIVATE_KEY_CONTENTS_HERE"
Note: When setting the
PrivateKey, paste the full content of the.pemfile, including the-----BEGIN RSA PRIVATE KEY-----and-----END RSA PRIVATE KEY-----markers. -
Configure the organization name in
appsettings.json:{ "GitHubApp": { "OrganizationName": "your-organization-name" } }Replace
your-organization-namewith your GitHub organization's slug.
To create a GitHub App for backend services:
- Go to GitHub Developer Settings
- Click "New GitHub App"
- Configure the following:
- GitHub App name: 10x GitHub Policy Enforcer
- Homepage URL:
https://localhost:7040/(for local development) - Webhook URL: Leave empty for local development
- Repository permissions:
- Administration: Read & write (to archive repositories)
- Contents: Read-only (to check for file presence)
- Issues: Read & write (to create and check for duplicate issues)
- Metadata: Read-only (to list repositories)
- Organization permissions: None required
- After creating the app:
- Note the App ID (found on the app's general page)
- Generate a Private Key (download the
.pemfile) - Install the app on your organization and note the Installation ID
For user authentication, you need to create a GitHub OAuth App:
- Go to GitHub Developer Settings
- Click "New OAuth App"
- Configure the following:
- Application Name: 10x GitHub Policy Enforcer
- Homepage URL:
https://localhost:7040/(for local development) - Authorization Callback URL:
https://localhost:7040/signin-github
- Note the Client ID and Client Secret
- Set the OAuth App secrets:
dotnet user-secrets set "GitHub:ClientId" "YOUR_OAUTH_APP_CLIENT_ID" dotnet user-secrets set "GitHub:ClientSecret" "YOUR_OAUTH_APP_CLIENT_SECRET"
The policy configuration is managed via a config.yaml file located in the root of your organization's .github repository.
Here is an example configuration:
# .github/config.yaml
# Access control: Specify the GitHub team authorized to access the dashboard.
# Format: 'organization-slug/team-slug'
authorized_team: 'my-org/security-team'
# Policies: Define the rules to enforce across your organization's repositories.
policies:
- name: 'Check for AGENTS.md'
type: 'has_agents_md'
action: 'create_issue' # 'create_issue', 'archive_repo', or 'log_only'
issue_details:
title: 'Compliance: AGENTS.md file is missing'
body: 'This repository is missing the AGENTS.md file in its root directory. Please add this file to comply with organization standards.'
labels: ['policy-violation', 'documentation']
- name: 'Check for catalog-info.yaml'
type: 'has_catalog_info_yaml'
action: 'create_issue'
issue_details:
title: 'Compliance: catalog-info.yaml is missing'
body: 'This repository is missing the catalog-info.yaml file. This file is required for backstage.io service discovery.'
labels: ['policy-violation', 'backstage']
- name: 'Verify Workflow Permissions'
type: 'correct_workflow_permissions'
action: 'log_only'The project employs a comprehensive multi-level testing strategy:
-
10xGitHubPolicies.Tests - Unit tests
- Services, policies, and business logic
- Blazor component tests using bUnit
- Run:
dotnet test 10xGitHubPolicies.Tests/10xGitHubPolicies.Tests.csproj
-
10xGitHubPolicies.Tests.Integration - Integration tests
- 33 tests for GitHubService with WireMock.Net
- HTTP-level mocking of GitHub API
- Coverage: file operations, repositories, issues, workflow permissions, rate limiting, token caching, team membership
- Run:
dotnet test 10xGitHubPolicies.Tests.Integration/10xGitHubPolicies.Tests.Integration.csproj --filter "Category=Integration"
-
10xGitHubPolicies.Tests.Contracts - Contract tests
- 11 tests validating GitHub API response contracts
- Schema validation using NJsonSchema (6 tests)
- Snapshot testing using Verify.NET (5 tests)
- Coverage: repository, issue, and workflow permissions responses
- Run:
dotnet test 10xGitHubPolicies.Tests.Contracts/10xGitHubPolicies.Tests.Contracts.csproj --filter "Category=Contract"
-
10xGitHubPolicies.Tests.E2E - End-to-end tests
- Browser automation tests using Playwright
- Full workflow testing from UI to database
- Uses Test Mode for authentication bypass (see Test Mode section)
- Requires Playwright browsers installation:
pwsh bin/Debug/net8.0/playwright.ps1 install chromium - Note: Web application must be running manually before executing E2E tests
- Run:
dotnet test 10xGitHubPolicies.Tests.E2E/10xGitHubPolicies.Tests.E2E.csproj
dotnet testA local testing script is available to replicate the GitHub Actions pull request workflow locally:
./test-workflow-local.shThis script executes the same sequence as the CI/CD pipeline:
- Linting: Code formatting verification
- Unit Tests: Fast business logic validation
- Component Tests: Blazor UI component testing
- Integration Tests: GitHub API integration with WireMock
- Contract Tests: API contract validation
Test results are saved to the ./coverage directory as TRX files for analysis.
Note: This script uses the same test filters and logging configuration as the GitHub Actions workflow, ensuring consistency between local and CI environments.
For more details, see Testing Strategy and CI/CD Workflows.
The project uses Dependabot to automatically keep dependencies up to date.
Dependabot is configured via .github/dependabot.yml and monitors the following:
- NuGet Packages (.NET): Weekly updates with conventional commit prefixes (
chore(nuget)) - GitHub Actions: Weekly updates for workflow action versions (
chore(github-actions)) - Docker Dependencies: Weekly updates for Docker images in
docker-compose.yml(chore(docker))
- Update Schedule: Weekly checks
- Cooldown Period: 14 days to prevent update spam and malware
- Pull Request Limits:
- NuGet: Up to 10 concurrent PRs
- GitHub Actions: Up to 5 concurrent PRs
- Docker: Up to 5 concurrent PRs
- Commit Messages: Follow conventional commit format with scoped prefixes
- Reviewers: Pull requests are automatically assigned for review
- Labels: Automatic labeling (
dependencies,nuget,github-actions,docker)
Dependabot pull requests automatically run through the same CI/CD pipeline as regular pull requests, including:
- Code formatting checks
- Unit, component, integration, and contract tests
- Code coverage reporting
You can review and merge these updates through the standard pull request process.
Detailed documentation for specific features and integrations:
- Authentication: User authentication and authorization system
- GitHub Integration: How to use the GitHub API service for repository management
- GitHub Client Factory: Factory pattern for testable GitHub API integration
- Configuration Service: Managing centralized policy configuration from
.github/config.yaml - Action Service: Automated action processing for policy violations
- Hangfire Integration: Background job processing and scheduling
- Policy Evaluation: How the policy evaluation engine works and how to add new policies
- Testing Strategy: Comprehensive testing approach, tooling, and best practices
- Contract Testing: Detailed guide to contract testing with WireMock, Verify.NET, and JSON Schema
- E2E Testing: Complete guide to End-to-End testing with Playwright
- CI/CD Workflows: GitHub Actions workflows, code coverage, and automated testing pipelines
For production, use GitHub Actions with Azure OIDC (workload identity federation) and Azure Managed Identity (MSI) for secretless SQL access.
- Guide: Production Deployment (Azure OIDC + MSI)
- CI migrations: run EF Core migrations via MSI using the console runner:
dotnet run --project Tools/DbMigrator/DbMigrator.csproj --configuration Release- ✅
[done]Configuration managed via a singleconfig.yamlfile in the.githubrepository. - ✅
[done]Daily and on-demand scanning of all active repositories. - ✅
[done]Core policies:- ✅
[done]Verify presence ofAGENTS.md. - ✅
[done]Verify presence ofcatalog-info.yaml. - ✅
[done]Verify repository Workflow Permissions are set to 'Read repository contents and packages permissions'.
- ✅
- ✅
[done]Automated actions:- ✅
[done]Create a GitHub Issue in the non-compliant repository with duplicate prevention. - ✅
[done]Archive the non-compliant repository. - ✅
[done]Log-only actions for monitoring without taking automated steps. - ✅
[done]Comprehensive action logging with status tracking.
- ✅
- ✅
[done]A simple dashboard showing non-compliant repositories, violation details, overall compliance percentage, and a repository name filter. - ✅
[done]Authentication via "Login with GitHub" OAuth flow. - ✅
[done]Access restricted to a specified GitHub Team.
- Automatically fixing policy violations (e.g., creating the missing file).
- Support for other version control systems (e.g., GitLab, Bitbucket).
- Advanced policy types (e.g., checking file content, branch protection rules).
- User-level permissions within the application.
- Repository-level exceptions or overrides in the UI.
- Logs - production
- Advanced policy types (e.g., checking file content)
- Action - PR Blocking
- Action - Log only
- Action - Slack notification
- Action - Fix (update github settings)
- Exception policies
- Getting team ownership
- Better project structure e.g. FrontEnd/UI
- Remove dups between .ai and /docs
- Review test coverage
- E2E tests and scenatios improvements
Distributed under the MIT License. See LICENSE for more information.