Sector facing output of the SAP (School Account Profile) project. This service allows schools to manage and update their profile information.
- Overview
- Prerequisites
- Getting Started
- Running Locally
- Running with Docker
- Project Structure
- Key Features
- Health Checks
- Environment Variables
- API Endpoints
- Testing
- Deployment
- Contributing
- Support
The SAP Sector service is a web application built with ASP.NET Core 8.0 that provides a user interface for schools to:
- Schools can view and comapare with similar schools
- Schools should use DSI Signing in to authenticate
The application uses the GOV.UK Design System and DfE Frontend for a consistent, accessible user experience following government design standards.
- .NET 8.0 SDK
- Node.js 22.x (for building frontend assets)
- Docker Desktop (optional, for containerized development)
- Visual Studio 2022 or Visual Studio Code (recommended)
git clone https://github.com/DFE-Digital/sap-sector.git
cd sap-sectordotnet restorecd SAPSec.Web
npm install
cd ..The npm install command automatically runs a postinstall script that copies GOV.UK Frontend and DfE Frontend libraries from node_modules to wwwroot/lib/.
cd SAPSec.Web
dotnet runThe application will be available at http://localhost:3000
- Open
sap-sector.slnin Visual Studio - Press
F5to run with debugging (orCtrl+F5without debugging) - The application will launch in your default browser
- Open the project folder in VS Code
- Press
F5to start debugging - Select ".NET Core Launch (web)" configuration
- Navigate to
http://localhost:3000
docker build -t sapsec:latest .The Docker build process:
- Assets stage: Builds frontend assets using Node.js
- Build stage: Compiles .NET application
- Final stage: Creates minimal runtime image
docker run -p 3000:3000 sapsec:latestThe application will be available at http://localhost:3000
sap-sector/
├── .github/
│ └── workflows/ # GitHub Actions CI/CD pipelines
│ ├── build-and-deploy.yml
│ ├── build-nocache.yml
│ └── delete-review-app.yml
├── SAPSec.Core/ # Domain models and business logic
│ └── SAPSec.Core.csproj
├── SAPSec.Infrastructure/ # Data access and external services
│ ├── Data/ # Database context (future)
│ └── SAPSec.Infrastructure.csproj
├── SAPSec.Web/ # Web application (MVC)
│ ├── Controllers/ # MVC Controllers
│ │ ├── HomeController.cs
│ │ └── HealthController.cs
│ ├── Views/ # Razor views
│ │ ├── Home/
│ │ └── Shared/
│ ├── wwwroot/ # Static files
│ │ ├── assets/ # Custom assets (images)
│ │ ├── css/ # Custom stylesheets
│ │ └── lib/ # Frontend libraries (auto-generated)
│ ├── Helpers/ # Helper classes
│ ├── package.json # Node.js dependencies
│ └── Program.cs # Application entry point
├── terraform/
│ └── application/ # Terraform infrastructure
├── Dockerfile # Docker configuration
├── .dockerignore # Docker ignore patterns
├── .gitignore # Git ignore patterns
└── README.md # This file
The application uses:
- GOV.UK Frontend v5.12.0 - Standard GOV.UK design system components
- DfE Frontend v2.0.1 - Department for Education branding and components
Frontend assets are automatically managed:
- Installed via npm from official packages
- Copied to
wwwroot/lib/duringnpm installvia postinstall script - Not committed to Git (regenerated during Docker build)
Custom DfE header with:
- Department for Education branding
- Service name display
- Alpha phase banner
- Mobile-responsive design
The application implements strict Content Security Policy headers for security:
- Nonce-based script execution
- Restricted external domains (Google Analytics, Microsoft Clarity, Application Insights)
- Protection against XSS and injection attacks
- Font and style restrictions
Keys are persisted to /keys directory for:
- Session management
- Anti-forgery tokens
- Data protection across deployments
The application provides two health check endpoints for monitoring:
Simple endpoint used by Kubernetes liveness/readiness probes and the deployment pipeline.
Response (200 OK):
Healthy
Usage:
curl http://localhost:3000/healthcheckComprehensive endpoint providing detailed status information for monitoring and diagnostics.
Response (200 OK):
{
"status": "Healthy",
"timestamp": "2025-01-15T10:30:00Z",
"checks": [
{
"name": "ApplicationRunning",
"status": "Pass",
"message": "SAPSec.Web is running in Production environment"
},
{
"name": "StaticFiles",
"status": "Pass",
"message": "Static files accessible: assets OK, CSS OK, libraries OK"
}
]
}Response (500 Internal Server Error):
{
"status": "Unhealthy",
"timestamp": "2025-01-15T10:30:00Z",
"checks": [
{
"name": "StaticFiles",
"status": "Fail",
"message": "wwwroot directory not found"
}
]
}Usage:
# Check health status
curl http://localhost:3000/health
# Check and pretty-print JSON
curl http://localhost:3000/health | jq '.'Checks performed:
- ✅ Application is running
- ✅ Static files exist and are accessible
- 💤 Database connectivity (ready to enable when database is added)
| Variable | Description | Default | Required |
|---|---|---|---|
ASPNETCORE_ENVIRONMENT |
Application environment | Production |
No |
ASPNETCORE_URLS |
URLs the application listens on | http://+:3000 |
No |
ASPNETCORE_FORWARDEDHEADERS_ENABLED |
Enable forwarded headers for proxies | true |
For AKS |
| Endpoint | Method | Description | Response |
|---|---|---|---|
/ |
GET | Home page | HTML |
/health |
GET | Detailed health check | JSON |
/healthcheck |
GET | Basic health check | Text |
/Home/Privacy |
GET | Privacy policy page | HTML |
/Home/Error |
GET | Error page | HTML |
dotnet testdotnet test /p:CollectCoverage=true /p:CoverageReporter=opencover# Start the application
dotnet run --project SAPSec.Web
# In another terminal, test the health endpoint
curl http://localhost:3000/healthReview apps provide temporary, isolated environments for testing pull requests before merging.
-
Triggering Deployment:
- Open your pull request on GitHub
- Add the
deploylabel from the labels menu - GitHub Actions automatically builds and deploys your branch
-
Deployment Process:
Add 'deploy' label → Build Docker image → Deploy to AKS → Health checks → Comment with URLDuration: ~5-10 minutes
-
Accessing Your Review App:
- URL Format:
https://sap-sector-{NUMBER}.test.education.gov.uk - Example: For PR #42:
https://sap-sector-42.test.education.gov.uk - Find the URL in:
- PR comments (posted by GitHub Actions)
- "Environments" section on the PR page
- GitHub Actions workflow logs
- URL Format:
-
Testing in Review App:
# Replace {PR_NUMBER} with your actual PR number export REVIEW_URL="https://sap-sector-{PR_NUMBER}.test.education.gov.uk" # Test the application curl $REVIEW_URL # Check health endpoints curl $REVIEW_URL/health | jq '.' curl $REVIEW_URL/healthcheck
-
Updating the Review App:
- Push new commits to your PR branch
- The review app automatically redeploys with your latest changes
- No need to remove/re-add the label
-
Sharing with Stakeholders:
- Copy the review app URL from PR comments
- Share with team members, testers, or stakeholders
- Everyone can test the changes before merging
-
Cleanup:
- Review app is automatically deleted when:
- PR is closed
- PR is merged
deploylabel is removed
- No manual cleanup required
- Review app is automatically deleted when:
✅ Test in production-like environment before merging
✅ Share live preview with non-technical stakeholders
✅ Verify integrations with external services
✅ Check responsive design on real devices
✅ Validate infrastructure changes safely
✅ Automatic cleanup - no manual management
Deployment failed:
- Check GitHub Actions logs for errors
- Verify Docker build succeeded
- Ensure all tests pass
- Check health check endpoint returns 200
Can't access review app URL:
- Wait 5-10 minutes for initial deployment
- Check PR comments for the correct URL
- Verify
deploylabel is applied - Check GitHub Actions workflow completed successfully
Changes not appearing:
- Push a new commit to trigger redeployment
- Check GitHub Actions shows deployment completed
- Clear browser cache and refresh
The project uses GitHub Actions for automated deployment. Workflows are located in .github/workflows/:
┌─────────────────────────────────────────────────────────────────┐
│ Developer pushes to feature branch │
└────────────────┬────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Creates Pull Request │
│ • CI builds and tests automatically run │
│ • Docker image is built and cached │
└────────────────┬────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Add 'deploy' label (Optional) │
│ • Triggers deployment to review environment │
│ • Creates temporary URL for testing │
│ • Runs health checks │
│ • Posts URL in PR comments │
└────────────────┬────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PR Approved & Merged to main │
│ • Automatic deployment to test environment │
│ • Health checks verify deployment │ │
└────────────────┬────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Manual promotion to production (Future) │
└─────────────────────────────────────────────────────────────────┘
Main deployment workflow that handles:
On Pull Request:
- ✅ Builds Docker image
- ✅ Runs unit tests
- ✅ Caches build artifacts
- ✅ Runs security scan with Snyk
- ✅ If
deploylabel added: Deploys to review environment
On Push to main:
- ✅ Builds production Docker image
- ✅ Runs all tests
- ✅ Deploys to test environment
- ✅ Runs health checks (
/healthcheckendpoint)
Health Check Verification:
# The deploy-to-aks action automatically:
1. Deploys the application
2. Waits for pods to be ready
3. Checks /healthcheck endpoint
4. Retries if unhealthy (up to 5 times)
5. Fails deployment if health check doesn't passBuilds Docker image without using cache (for troubleshooting build issues)
Automatically cleans up review environments when PRs are closed or merged
| Environment | Trigger | URL |
|---|---|---|
| Review | PR with deploy label |
Dynamic per PR |
| Test | Push to main |
TBD |
| Production | Manual approval | TBD |
The application is deployed to Azure Kubernetes Service with:
- Health probes configured for
/healthcheckendpoint - Auto-scaling based on CPU/memory metrics
- Horizontal pod autoscaling (HPA)
- Non-root container execution (user 1654)
- Data protection keys persisted to
/keys
Infrastructure is managed with Terraform:
- Configuration located in
terraform/application/ - Deployed via GitHub Actions
- Includes AKS cluster, networking, and monitoring
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes:
- Write code following C# conventions
- Add/update tests
- Update documentation
-
Test locally:
dotnet build dotnet test dotnet run --project SAPSec.Web # Test health endpoints curl http://localhost:3000/health curl http://localhost:3000/healthcheck
-
Commit your changes:
git add . git commit -m "feat: add new feature"
-
Push to GitHub:
git push origin feature/your-feature-name
-
Create a Pull Request:
- Go to https://github.com/DFE-Digital/sap-sector/pulls
- Click "New Pull Request"
- Select your branch as the compare branch
- Add a clear title and description of changes
- Request reviews from team members
-
Deploy to Review Environment (Optional):
To test your changes in a live environment before merging:
a. Add the
deploylabel to your PR:- On your PR page, click "Labels" on the right sidebar
- Select or type
deploy - Click outside the dropdown to apply
b. GitHub Actions will automatically:
- Build a Docker image with your changes
- Deploy to a temporary review environment in AKS
- Run health checks to verify the deployment
- Add a comment to your PR with the review app URL
c. Access your review app:
- Look for the environment URL in the PR comments
- Format:
https://sap-sector-review-pr-{PR_NUMBER}.test.education.gov.uk - Example:
https://sap-sector-review-pr-123.test.education.gov.uk
d. Verify your changes:
- Test all functionality in the review environment
- Check that UI changes appear correctly
- Verify health endpoints work:
{URL}/healthand{URL}/healthcheck - Share the URL with reviewers for testing
e. Review app lifecycle:
- Created automatically when
deploylabel is added - Updated automatically on each new push to the PR branch
- Deleted automatically when the PR is closed or merged
-
Get Approval and Merge:
- Address any review comments
- Ensure all CI checks pass (build, tests, health checks)
- Get at least one approval
- Merge the PR (squash and merge recommended)
-
Automatic Deployment:
- After merging to
main, changes automatically deploy totestenvironment - Monitor the deployment in GitHub Actions
- Verify health checks pass in test environment
- After merging to
- Follow C# Coding Conventions
- Use meaningful variable and method names
- Add XML documentation comments for public APIs
- Write unit tests for new functionality
- Keep methods small and focused (Single Responsibility Principle)
Follow the Conventional Commits specification:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat:- New featurefix:- Bug fixdocs:- Documentation changesstyle:- Code style changes (formatting, no logic change)refactor:- Code refactoringtest:- Adding or updating testschore:- Maintenance tasks
Examples:
feat(health): add database connectivity check
fix(auth): resolve session timeout issue
docs: update deployment instructions in README
test(controllers): add unit tests for HealthController
- Keep PRs focused and small (ideally < 400 lines changed)
- Write clear, descriptive titles using conventional commits format
- Test your changes locally
- Ensure all tests pass:
dotnet test - Check code builds without errors:
dotnet build
-
Title Format:
<type>(<scope>): <description> Examples: feat(health): add database connectivity check fix(auth): resolve session timeout issue docs: update deployment instructions -
Description Template:
## What Brief description of what this PR does ## Why Explanation of why this change is needed ## How to Test Steps to verify the changes: 1. Step one 2. Step two 3. Expected result ## Screenshots (if applicable) [Add screenshots of UI changes] ## Checklist - [ ] Tests added/updated - [ ] Documentation updated - [ ] Tested locally - [ ] Ready for review
When to use review apps:
- Testing UI changes with stakeholders
- Verifying integration with external services
- Demonstrating new features
- Testing in a production-like environment
How to deploy:
- Add
deploylabel to your PR - Wait for GitHub Actions to complete (~5-10 minutes)
- Find the review app URL in PR comments or environments tab
- Share URL with reviewers for testing
Important notes:
- Review apps are temporary (deleted when PR closes)
- Each PR gets its own isolated environment
- Changes are automatically redeployed on every push
- Review apps use the same configuration as test environment
- Minimum 1 approval required before merging
- All CI checks must pass (build, tests, health checks)
- Address all review comments or mark them as resolved
- Keep the PR updated by pulling latest changes from main
- Use "Request changes" for blocking issues
- Use "Comment" for non-blocking suggestions
- Use "Squash and merge" (preferred) to keep history clean
- Ensure commit message follows conventional commits
- Delete the branch after merging
- Monitor deployment to test environment
- Slack:
#sap-sector-support(DfE Digital Slack workspace) - Email: sap-sector-team@education.gov.uk
- Issues: GitHub Issues
When reporting bugs, please include:
- Environment (local/review/test/production)
- Steps to reproduce
- Expected behavior
- Actual behavior
- Screenshots (if applicable)
- Browser/OS information (for UI issues)
- DfE Technical Guidance
- GOV.UK Design System
- DfE Design Manual
- ASP.NET Core Documentation
- Azure Kubernetes Service
- GitHub Actions
MIT License - Crown Copyright (Department for Education)
Maintained by: DfE Digital - SAP Sector Team
Last Updated: January 2025