| Pipeline |
|---|
| Environment | Status | Link |
|---|---|---|
| QA | https://mvc-app-qa-663949819005.us-central1.run.app | |
| Production | https://mvc-app-prod-663949819005.us-central1.run.app |
ctf-sandbox
https://github.com/users/CurlyFire/projects/4/views/1
MIT
This is a TDD Sandbox to work out the kinks to migrate from a big ball of mud legacy project to a microservice hexagonal architecture with unit tests that respect the modern test pyramid.
The main goals of this project are:
- âś… Generate a big ball of mud to represent the initial legacy application
- 🔄 Migrate to a microservices hexagonal architecture with unit tests
- 🔄 Get my DDD Bounded Contexts framed correctly
- 🔄 Develop all this code in TDD, following Valentina Jemuovic's suggested way. Her site is Optivem journal. You can also follow her on LinkedIn
The big ball of mud was created with github copilot agent mode using Claude Sonnet 3.5. I just wanted to create something that worked without being clean.
MVC monolith
C4Context
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
Person(user, "Competitor", "Creates or participates in CTF competitions")
Enterprise_Boundary(b0, "CTF") {
System(systemctf, "CTF Sandbox", "Manage challenges, teams, and competitions")
System_Ext(systememail, "E-mail system", "SMTP testing tool for development")
System_Ext(systemipinfo, "Ip Lookup system", "Ip information lookup")
Rel(user, systemctf, "Registers, creates teams, participates")
UpdateRelStyle(user, systemctf, $offsetX="-230", $offsetY="-45")
Rel(systemctf, systememail, "Sends email")
UpdateRelStyle(systemctf, systememail, $offsetX="-40", $offsetY="-10")
Rel(systemctf, systemipinfo, "Lookup ip")
UpdateRelStyle(systemctf, systemipinfo, $offsetX="10", $offsetY="-10")
}
C4Container
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
Person(user, "User", "Creates or participates in CTF competitions")
System_Boundary(ctf, "CTF Sandbox") {
Container(webapp, "Web Application (ASP.NET MVC)", "C#", "Handles UI, business logic, and data access")
Container_Ext(mailpit, "E-mail System", "SMTP / Dev Tool", "Receives email notifications from the app")
ContainerDb(sqlite, "SQLite Database", "SQL", "Stores users, teams, challenges, competitions")
Container_Ext(systemipinfo, "Ip Lookup system", "HTTP REST", "Resolves ip information")
Rel(user, webapp, "Uses")
UpdateRelStyle(user, webapp, $offsetX="-50", $offsetY="-20")
Rel(webapp, sqlite, "Reads from and writes to", "SQL")
UpdateRelStyle(webapp, sqlite, $offsetX="-50", $offsetY="-20")
Rel(webapp, mailpit, "Sends email via SMTP")
UpdateRelStyle(webapp, mailpit, $offsetX="-50", $offsetY="-30")
Rel(webapp, systemipinfo, "Lookups ip information")
UpdateRelStyle(webapp, mailpit, $offsetX="-50", $offsetY="-30")
}
The CTF competition UI has all the features mentionned in the Sytem use cases section. Mailpit is used as a SMPT server for invitations and registrations, however, the emails all stay there and can be seen from the mailpit UI. If you require access to it, ask me and I will create a user for you to view all emails.
Each environment has it's own external system docker container instances. The test environments (acceptance, E2E, docker-compose) also have their own external test instances, however they are ephemeral and last only for the duration of the tests, so no links are provided here.
| Real | Stubbed | |
|---|---|---|
| Mailpit Docker container | Mailpit Docker container | |
| Ip info | https://ipinfo.io | WireMock |
| Time | System clock | WireMock |
As the protocols to communicate are smtp and http, to switch between real or stubbed, you only have to change the Email settings described in the Configuring external system connections section.
as the protocol to communicate is http, to switch between real or stubbed, you only have to change the Ipinfo settings described in the Configuring external system connections section.
The contract used to get the current time is through the abstract class System.TimeProvider. To switch between real or stubbed, you only have to change the configuration settings between the system or http TimeProvider, like this:
{
# Use these settings to use the system clock
"TimeProvider": {
"Type": "system"
}
# OR use these settings to use a stubbed WireMock provider that returns the time as a utc string
"TimeProvider": {
"Type": "http",
"Url": "http://wiremockserver/api/time"
},
}
| Environment | External system | Link |
|---|---|---|
| QA | Mailpit | https://mailpit-ui-qa-663949819005.us-central1.run.app/ |
| Production | Mailpit | https://mailpit-ui-prod-663949819005.us-central1.run.app/ |
To configure which external system is used by the mvc-app, override the following configurations using either appsettings.web.json or environment variables as explained in this article https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-9.0 It is suggested to override through the appsettings.web.dev.json, as this file is git ignored, but is optionaly read by the application, and has a higher priority than appsettings.web.json
example with appsettings.json
{
"EmailSettings": {
# Change these values to connect to a different mailpit instance
"SmtpServer": "mailpit",
"SmtpPort": 1025,
"MailpitUrl": "http://localhost:8025"
},
"IPInfo": {
# Change these values to connect to a different ipinfo instance
"Token": "MySecretToken",
"BaseUrl": "https://ipinfo.io"
},
}
Programming language: C#
Frameworks: ASP.Net Core MVC
Database: Sqlite
Mono-Repo
CI/CD is enabled for the main branch and will deploy to the Acceptance environement automatically.
Responsible for writing the software and maintaining the PageObjectModels and Tests.
Responsible for writing addditional E2E tests.
- Make sure you have installed the software requirements
- Clone the repository
- Open the cloned folder within Visual Studio Code
- Reopen the folder inside a devcontainer (Visual Studio's Dev container extension should detect the devcontainer configuration)
- (optional) If you wish to work on pipelines locally, make sure to run dev-scripts/authenticate.ps1, as this will authenticate you to gcloud and github
- Make sure you have completed the Prerequisites
- Just press F5 and the debug task will start the application and a browser on the server address
- Open up a terminal from within Visual Studio Code
- Execute ./dev-scripts/run.ps1
- Open a browser to the listening url (usually http://localhost:5191)
- Make sure you have completed the Prerequisites
- Nagivate to the test explorer
- Refresh the tests by pressing the refresh button
- Run the tests by pressing the play button
- Open up a terminal from within Visual Studio Code
- Execute ./dev-scripts/run-tests.ps1