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
44 changes: 34 additions & 10 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Deploy to Amazon Linux EC2

on:
workflow_dispatch:
push:
branches:
- "**"
Expand All @@ -20,7 +21,7 @@ jobs:
- name: Set up .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0.100"
dotnet-version: "10.0.x"

- name: Install bun
uses: oven-sh/setup-bun@v2
Expand All @@ -32,7 +33,15 @@ jobs:
RAYGUN_API_KEY: ${{ secrets.RAYGUN_API_KEY }}

- name: Publish .NET Core app
run: dotnet publish Minigun.sln -c Release -o ./publish -p:PublishEnvironment=CI
run: >
dotnet publish src/Minigun/Minigun.csproj
-c Release
-r linux-arm64
--self-contained true
-o ./publish
-p:PublishEnvironment=CI
-p:PublishSingleFile=true
-p:IncludeNativeLibrariesForSelfExtract=true

- name: Stop Application on EC2
env:
Expand All @@ -48,11 +57,19 @@ jobs:
echo -e "Host *\n\tStrictHostKeyChecking no" > ~/.ssh/config

ssh -i ./ec2_key.pem $EC2_USER@$EC2_HOST << 'EOF'
sudo pkill Minigun || true
sudo systemctl stop minigun || true
EOF

sleep 2

- name: Prepare deployment directory on EC2
env:
EC2_HOST: ${{ secrets.EC2_HOST }}
EC2_USER: ${{ secrets.EC2_USER }}
DEPLOY_DIR: /var/www/minigun
run: |
ssh -i ./ec2_key.pem $EC2_USER@$EC2_HOST "sudo mkdir -p '$DEPLOY_DIR' && sudo chown -R '$EC2_USER' '$DEPLOY_DIR' && sudo chmod 755 '$DEPLOY_DIR'"

- name: Upload files to EC2
env:
EC2_HOST: ${{ secrets.EC2_HOST }}
Expand All @@ -61,15 +78,25 @@ jobs:
DEPLOY_DIR: /var/www/minigun
run: |
# Upload files to EC2
scp -i ./ec2_key.pem -r ./publish/* $EC2_USER@$EC2_HOST:$DEPLOY_DIR
scp -i ./ec2_key.pem -r ./publish/* $EC2_USER@$EC2_HOST:$DEPLOY_DIR/

# Upload systemd unit file and install it
scp -i ./ec2_key.pem ./deploy/minigun.service $EC2_USER@$EC2_HOST:/tmp/minigun.service
ssh -i ./ec2_key.pem $EC2_USER@$EC2_HOST << 'EOF'
sudo mv /tmp/minigun.service /etc/systemd/system/minigun.service
sudo chown root:root /etc/systemd/system/minigun.service
sudo chmod 644 /etc/systemd/system/minigun.service
sudo systemctl daemon-reload
sudo systemctl enable minigun
EOF

- name: Create Raygun Deployment
uses: MindscapeHQ/raygun-deployments-action@v1
with:
personal-access-token: ${{ secrets.RAYGUN_PAT }}
api-key: ${{ secrets.RAYGUN_API_KEY }}
version: ${{ steps.vars.outputs.sha_short }}
comment: ${{ github.event.head_commit.message }}
comment: ${{ github.event.head_commit.message || format('Manual deployment for {0}', github.sha) }}

- name: Start Application on EC2
env:
Expand All @@ -81,11 +108,8 @@ jobs:
ssh -i ./ec2_key.pem $EC2_USER@$EC2_HOST << EOF
set -x

cd $DEPLOY_DIR
sudo nohup ./Minigun > minigun.log 2>&1 &

ps aux | grep Minigun
tail -n 20 minigun.log
sudo systemctl start minigun
sudo systemctl status minigun --no-pager
EOF

- name: Clean up
Expand Down
6 changes: 3 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand All @@ -18,6 +18,6 @@
</PropertyGroup>

<PropertyGroup Condition="'$(PublishEnvironment)' == 'CI'">
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<RuntimeIdentifier>linux-arm64</RuntimeIdentifier>
</PropertyGroup>
</Project>
</Project>
7 changes: 7 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,12 @@
<ItemGroup>
<PackageVersion Include="Mindscape.Raygun4Net.AspNetCore" Version="11.2.1" />
<PackageVersion Include="Mindscape.Raygun4Net.NetCore.Common" Version="11.2.1" />
<PackageVersion Include="Serilog" Version="4.3.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageVersion Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageVersion Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageVersion Include="Serilog.Sinks.Raygun" Version="8.2.0" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.0" />
</ItemGroup>
</Project>
17 changes: 17 additions & 0 deletions deploy/minigun.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[Unit]
Description=Minigun ASP.NET Core Application
After=network.target

[Service]
WorkingDirectory=/var/www/minigun
ExecStart=/var/www/minigun/Minigun
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=minigun
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,16 @@ [FromQuery] DateTime endTime

return PartialView("_ErrorTimeseries", errorTimeseries);
}

[HttpGet("/crashreporting/error-group-count")]
public async Task<IActionResult> ErrorGroupCount(
[FromQuery] string applicationIdentifier,
[FromQuery] string errorGroupId,
[FromQuery] DateTime startTime,
[FromQuery] DateTime endTime
)
{
var count = await _raygunApiService.GetErrorGroupCountAsync(applicationIdentifier, errorGroupId, startTime, endTime);
return Content(count.ToString("N0"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@model Minigun.Models.ErrorGroup

@using Minigun.Utilities

<tr class="bg-white border-b hover:bg-gray-50">
<td class="w-12 p-4">
<div class="flex items-center">
<input id="checkbox-@Model.Identifier" type="checkbox" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500">
<label for="checkbox-@Model.Identifier" class="sr-only">checkbox</label>
</div>
</td>
<td class="px-4 py-2 font-medium text-gray-900 truncate">
<a href="@Model.ApplicationUrl" class="font-medium text-blue-600 hover:underline">@Model.Message</a>
</td>
<td class="px-4 py-2 whitespace-nowrap text-gray-600">
@{
var lastSeenText = Model.LastOccurredAt.ToHumanReadableTimeAgo();
}
@lastSeenText
</td>
<td class="px-4 py-2 whitespace-nowrap text-gray-600">
@{
var firstSeenText = Model.CreatedAt.ToHumanReadableTimeAgo();
}
@firstSeenText
</td>
<td class="px-4 py-2 whitespace-nowrap text-gray-700 font-semibold"
hx-get="@Url.Action("ErrorGroupCount", "CrashReporting", new { Area = "CrashReporting" })"
hx-vals='{"applicationIdentifier": "@Context.Request.Query["applicationIdentifier"]", "errorGroupId": "@Model.Identifier", "startTime": "@Context.Request.Query["startTime"]", "endTime": "@Context.Request.Query["endTime"]"}'
hx-trigger="intersect once"
hx-target="#count-@Model.Identifier"
hx-indicator=".no-global-indicator">
<span id="count-@Model.Identifier" class="text-gray-400 animate-pulse">–</span>
</td>
</tr>
Loading
Loading