An automated system to fix GitHub Classroom repository access issues. This webhook-driven service automatically detects when new classroom repositories are created and ensures students have the correct access permissions by replacing invalid GitHub Classroom bot invitations.
- Problem Statement
- How It Works
- For Students: Access Troubleshooting
- Prerequisites
- Installation
- Configuration
- Local Development
- Deployment
- API Reference
- Architecture
- Monitoring & Metrics
- Security
- Performance
- Troubleshooting
- License
- Support
GitHub Classroom occasionally experiences issues where students cannot access newly created assignment repositories. The github-classroom[bot]
may send invitations that students cannot accept or that don't grant proper permissions. This system provides an automated, responsive solution that monitors repository creation events and immediately corrects access permissions by replacing problematic bot invitations.
The system addresses a specific GitHub Classroom issue where the github-classroom[bot]
sends invalid or inaccessible collaboration invitations to students. When students accept assignments, they receive invitations that may not work correctly.
The Solution:
- Webhook Monitoring: Listens for repository creation events from your GitHub organization
- Bot Invitation Detection: Checks if the newly created repository has any pending invitations from
github-classroom[bot]
- Bot Invitation Cleanup: Finds and deletes any pending invitations sent by
github-classroom[bot]
- Re-invitation: Sends fresh, valid invitations from your authenticated account with write access
- Automatic Permission Assignment: Ensures students get write access to their assignment repositories
This approach eliminates the need to parse complex repository names - instead, it simply finds ALL bot invitations and replaces them with valid ones that students can actually accept.
- Webhook-Based Detection: Monitors GitHub organization webhook events for new repository creation
- Bot Invitation Processing: Automatically detects and replaces invalid
github-classroom[bot]
invitations - Write Access by Default: Ensures students receive write access to their assignment repositories
- Universal Compatibility: Works with any repository naming pattern - no parsing required
- Enterprise-Ready: Production-grade security, monitoring, and error handling
- High Performance: Handles 100+ concurrent webhooks with <500ms response time
- Comprehensive Monitoring: Prometheus metrics and health checks included
(This section is for the instructor to guide students after this service is deployed.)
If you're a student who just accepted a GitHub Classroom assignment but showing "GitHub Repository Access Issue":
- Accept the assignment through the GitHub Classroom link provided by your instructor
- If you see an access error ("GitHub Access Issue"):
- Check your email inbox for a new collaboration invitation
- The email will be from GitHub with subject like "Invitation to collaborate on [repository-name]"
- Click the invitation link in the email to gain access
- Success! You should now have write access to your assignment repository
If you encounter the error shown above, simply check your email for the new invitation that was automatically sent to fix the access issue.
Sometimes GitHub Classroom's bot sends invitations that don't work properly. This automated system detects the issue and immediately sends you a new, working invitation from your instructor's account.
- Node.js 20.x or higher
- npm 9.x or higher
- GitHub Personal Access Token with
repo
andadmin:org
permissions - GitHub Organization with webhook access
- ngrok (for local development and testing)
For development and testing on your local machine:
- Clone the repository:
git clone https://github.com/nikmomo/GHClassroom.AccessFix.git
cd GHClassroom.AccessFix
- Install dependencies:
npm install
- Configure environment variables:
cp .env.example .env
# Edit .env with your configuration
- Set up ngrok for webhook tunneling:
# Install ngrok globally
npm install -g ngrok
# Start ngrok tunnel (in a separate terminal)
ngrok http 3000
-
Configure GitHub webhook:
- Use the ngrok HTTPS URL (e.g.,
https://abc123.ngrok.io/webhook/github
) - Follow the GitHub Webhook Setup instructions
- Use the ngrok HTTPS URL (e.g.,
-
Run in development mode:
npm run dev
For production deployment on a cloud server:
- Clone the repository on your server:
git clone https://github.com/nikmomo/GHClassroom.AccessFix.git
cd GHClassroom.AccessFix
- Install dependencies:
npm install --production
- Configure production environment:
# Create production environment file
cat > .env.production << 'EOF'
GITHUB_TOKEN=your_github_token_here
GITHUB_ORG=your_organization_name
WEBHOOK_SECRET=your_webhook_secret_here
PORT=3000
NODE_ENV=production
LOG_LEVEL=info
EOF
- Build the application:
npm run build
- Option A: Run with Node.js and PM2:
# Install PM2
npm install -g pm2
# Start application
pm2 start dist/index.js --name ghclassroom-fix
# Save PM2 configuration
pm2 save
pm2 startup
- Option B: Run with Docker:
# Build Docker image
docker build -t ghclassroom-fix:latest .
# Run container
docker run -d \
--name ghclassroom-fix \
--restart unless-stopped \
-p 3000:3000 \
--env-file .env.production \
ghclassroom-fix:latest
- Configure GitHub webhook:
- Use your server's public URL (e.g.,
https://your-server.com/webhook/github
) - Follow the GitHub Webhook Setup instructions
- Use your server's public URL (e.g.,
Variable | Description | Default | Required |
---|---|---|---|
GITHUB_TOKEN |
GitHub Personal Access Token | - | Yes |
GITHUB_ORG |
GitHub Organization name | - | Yes |
WEBHOOK_SECRET |
Webhook signature secret | - | Yes |
PORT |
Server port | 3000 | No |
NODE_ENV |
Environment (development/production/test) | development | No |
LOG_LEVEL |
Logging level (debug/info/warn/error) | info | No |
DRY_RUN |
Enable dry run mode (no actual changes) | false | No |
AUTO_ADD_COLLABORATOR |
Automatically add missing collaborators | true | No |
DEFAULT_PERMISSION |
Default permission level | push | No |
Your GitHub Personal Access Token must have the following permissions:
repo
- Full control of private repositories- Needed to: Access repository details, manage collaborators, read/write repository settings
admin:org
- Full control of orgs and teams, read and write org projects- Needed to: List organization repositories, manage organization member access
read:user
- Read access to user profile information- Needed to: Validate usernames and user existence
user:email
- Access user email addresses- Needed to: Send collaboration invitations via email
- Go to GitHub Settings β Developer settings β Personal access tokens β Tokens (classic)
- Click "Generate new token (classic)"
- Set expiration (recommended: 90 days for security)
- Select the required scopes listed above
- Click "Generate token"
- Important: Copy the token immediately - you won't be able to see it again
- Store the token securely in your environment variables
- Navigate to your GitHub Organization (e.g.,
https://github.com/VTECE
) - Click "Settings" tab (you need admin access to the organization)
- In the left sidebar, click "Webhooks"
- Click "Add webhook"
- You may be prompted to confirm your password
- Payload URL:
https://your-server-domain.com/webhook/github
- For local development with ngrok:
https://abc123.ngrok.io/webhook/github
- For cloud deployment:
https://your-app.example.com/webhook/github
- For local development with ngrok:
- Content type: Select
application/json
- Secret: Enter a strong, random string (save this for your
WEBHOOK_SECRET
env var)- Generate with:
openssl rand -base64 32
- Generate with:
- Choose "Let me select individual events"
- Uncheck "Pushes" (enabled by default)
- Check the following events:
- β Repositories (repository created/deleted, it only process created event)
- Ensure "Active" checkbox is checked
Important: You only need to monitor "Repository created" events. The system automatically processes GitHub Classroom bot invitations when new repositories are created - no additional webhook events are required.
- Click "Add webhook"
- GitHub will send a test ping event to verify connectivity
- Check the webhook's "Recent Deliveries" tab to confirm successful delivery
- Status should show green checkmark (β ) for successful delivery
After deploying your application:
# Test the webhook endpoint directly
curl -X GET https://your-server.com/health
# Expected response:
{
"status": "healthy",
"timestamp": "2025-09-06T20:00:00.000Z",
"version": "1.0.0",
"github": {
"connected": true,
"rateLimit": {
"remaining": 4985,
"reset": "2025-09-06T21:00:00.000Z"
}
}
}
- Student accepts GitHub Classroom assignment
- GitHub creates repository and sends webhook to your server
- Your server receives
repository.created
event - System checks repository for pending
github-classroom[bot]
invitations - If bot invitations exist:
- Deletes the bot invitations
- Sends fresh invitations from your authenticated account with write access
- Student receives working collaboration invitations they can actually accept
ngrok is essential for local development as it provides a secure tunnel to your local server, allowing GitHub webhooks to reach your development environment.
Option 1: Using npm (Recommended)
npm install -g ngrok
Option 2: Download from ngrok website
- Visit ngrok.com
- Download the appropriate version for your OS
- Extract and add to your PATH
- Start your local server:
npm run dev
# Server will run on http://localhost:3000
- In a new terminal, start ngrok:
ngrok http 3000
- ngrok will display a forwarding URL:
Forwarding: https://abc123def456.ngrok.io -> http://localhost:3000
-
Configure GitHub webhook with ngrok URL:
- Use the HTTPS URL from ngrok as your webhook payload URL
- Example:
https://abc123def456.ngrok.io/webhook/github
-
Update your local
.env
file (optional):
# If your application needs to know its public URL
PUBLIC_URL=https://abc123def456.ngrok.io
- Free tier limitations: ngrok free tier generates a new URL each time you restart. Update your webhook configuration accordingly.
- Inspect traffic: Visit
http://localhost:4040
to see all webhook requests and responses - Replay requests: Use ngrok's web interface to replay failed webhook deliveries for debugging
- Custom subdomain: Consider ngrok paid plans for consistent URLs during development
- Verify ngrok connection:
curl https://your-ngrok-url.ngrok.io/health
-
Create a test repository in your organization to trigger the webhook
-
Monitor logs in your terminal to see webhook processing
-
Check ngrok inspector at
http://localhost:4040
for request details
# Run in development mode with hot reload
npm run dev
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Lint code
npm run lint
# Format code
npm run format
# Type check
npm run typecheck
Enable debug logging for troubleshooting:
LOG_LEVEL=debug npm run dev
# Clone the repository
git clone https://github.com/nikmomo/GHClassroom.AccessFix.git
cd GHClassroom.AccessFix
# Create production environment file
cat > .env.production << 'EOF'
GITHUB_TOKEN=your_github_token_here
GITHUB_ORG=your_organization_name
WEBHOOK_SECRET=your_webhook_secret_here
PORT=3000
NODE_ENV=production
DRY_RUN=false
LOG_LEVEL=info
EOF
# Build the image
docker build -t ghclassroom-fix:latest .
# Verify the build
docker images | grep ghclassroom-fix
# Run in production mode
docker run -d \
--name ghclassroom-fix \
--restart unless-stopped \
-p 3000:3000 \
--env-file .env.production \
ghclassroom-fix:latest
# Check if it's running
docker ps
docker logs ghclassroom-fix
# Test health endpoint
curl http://localhost:3000/health
# Expected response should show "status": "healthy"
For production deployments, use Nginx for HTTPS termination:
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# View application logs
docker logs -f ghclassroom-fix
# Monitor resource usage
docker stats ghclassroom-fix
GET /health
Returns system health status and GitHub connection info.
GET /metrics
Returns Prometheus-formatted metrics.
POST /webhook/github
Receives and processes GitHub webhook events.
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β GitHub ββββββΆβ Webhook Server ββββββΆβ GitHub API β
β Organization β β (Express.js) β β (Octokit) β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β
βΌ
ββββββββββββββββββββ
β Bot Invitation β
β Processor β
ββββββββββββββββββββ
The system uses webhook-based detection rather than repository naming patterns:
- Webhook Trigger: Listens for
repository.created
webhook events from your GitHub organization - Bot Invitation Detection: When a repository is created, checks for pending invitations from
github-classroom[bot]
- Conditional Processing: Only processes repositories that have pending GitHub Classroom bot invitations
- Universal Compatibility: Works with any repository naming convention - no parsing or configuration needed
- Write Access by Default: Replaces bot invitations with fresh invitations granting write access
This webhook-based approach ensures the system responds immediately when GitHub Classroom creates new repositories, regardless of naming patterns.
webhook_processed_total
: Total webhooks processedwebhook_success_total
: Successful webhook processingswebhook_failed_total
: Failed webhook processingsprocess_uptime_seconds
: Process uptime
The /health
endpoint provides:
- GitHub connection status
- Rate limit information
- Processing metrics
- System uptime
- Webhook signature verification
- IP whitelisting support
- Security headers (HSTS, CSP, XSS Protection)
- Non-root Docker user
- Read-only filesystem in production
- Secret redaction in logs
- Response time: <500ms for webhook processing
- Concurrent handling: 100+ webhooks
- Memory usage: <512MB
- CPU usage: <0.5 cores
- Automatic retry with exponential backoff
- Rate limit handling
-
Webhook signature validation failing
- Verify the webhook secret matches exactly
- Check for trailing spaces in environment variables
-
Students not being added
- Verify GitHub token has correct permissions
- Check if student username exists on GitHub
- Review logs for specific error messages
-
Repository not being processed
- Verify the repository has pending
github-classroom[bot]
invitations - Check webhook delivery logs for "No GitHub Classroom bot invitations found" messages
- Enable debug logging to see invitation detection details
- Verify the repository has pending
-
ngrok connection issues
- Ensure ngrok is running and forwarding to the correct port
- Check if the ngrok URL has changed (free tier generates new URLs)
- Verify firewall settings allow ngrok connections
Enable debug logging:
LOG_LEVEL=debug npm run dev
MIT License - see LICENSE file for details.
- Create an issue for bug reports or feature requests
Built with enterprise-grade libraries:
- Express.js for the web server
- Octokit for GitHub API interaction
- Pino for structured logging
- Jest for testing
- Docker for containerization