mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 07:13:12 +00:00
fix(observability): preserve backend release identity (#114)
This commit is contained in:
parent
67089c2135
commit
3a4af64a64
4 changed files with 108 additions and 13 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Reflection;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Api.SeaHavenIndustries.Observability;
|
using Api.SeaHavenIndustries.Observability;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
|
@ -14,6 +15,7 @@ namespace Api.SeaHavenIndustries.Tests;
|
||||||
public class SentryObservabilityTests
|
public class SentryObservabilityTests
|
||||||
{
|
{
|
||||||
private static readonly string ValidSha = new string('a', 40);
|
private static readonly string ValidSha = new string('a', 40);
|
||||||
|
private static readonly string UpperSha = "ABCDEF0123456789ABCDEF0123456789ABCDEF01";
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ResolveRelease_Accepts_ServicePrefixed40HexCommit()
|
public void ResolveRelease_Accepts_ServicePrefixed40HexCommit()
|
||||||
|
|
@ -23,15 +25,57 @@ public class SentryObservabilityTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
[InlineData(null)]
|
||||||
[InlineData("1.0.0")]
|
[InlineData("1.0.0")]
|
||||||
[InlineData("shoc-backend@abc")]
|
[InlineData("shoc-backend@abc")]
|
||||||
[InlineData("shoc-backend@not-a-sha-at-all")]
|
[InlineData("shoc-backend@not-a-sha-at-all")]
|
||||||
[InlineData("other-service@" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
|
[InlineData("other-service@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
|
||||||
|
[InlineData("SHOC-BACKEND@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
|
||||||
[InlineData("")]
|
[InlineData("")]
|
||||||
public void ResolveRelease_FallsBackToLocalDevelopment_ForNonReleaseVersion(string version)
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
|
||||||
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
|
||||||
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")]
|
||||||
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+dirty")]
|
||||||
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+")]
|
||||||
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa++")]
|
||||||
|
[InlineData("shoc-backend@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+extra")]
|
||||||
|
public void ResolveRelease_FallsBackToLocalDevelopment_ForNonReleaseVersion(string? version)
|
||||||
{
|
{
|
||||||
SentryObservability.ResolveRelease(version)
|
SentryObservability.ResolveRelease(version)
|
||||||
.Should().Be(SentryObservability.LocalDevelopmentRelease);
|
.Should().Be(SentryObservability.LocalDevelopmentRelease);
|
||||||
|
SentryObservability.ResolveCommitSha(version)
|
||||||
|
.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveRelease_Accepts_SdkAppendedMatchingSourceRevisionSuffix()
|
||||||
|
{
|
||||||
|
var informationalVersion = "shoc-backend@" + ValidSha + "+" + ValidSha;
|
||||||
|
|
||||||
|
SentryObservability.ResolveRelease(informationalVersion)
|
||||||
|
.Should().Be("shoc-backend@" + ValidSha);
|
||||||
|
SentryObservability.ResolveCommitSha(informationalVersion)
|
||||||
|
.Should().Be(ValidSha);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveRelease_Accepts_SuffixDifferingOnlyInCase_FromTheCommitSha()
|
||||||
|
{
|
||||||
|
var canonicalSha = UpperSha.ToLowerInvariant();
|
||||||
|
|
||||||
|
SentryObservability.ResolveRelease("shoc-backend@" + UpperSha + "+" + canonicalSha)
|
||||||
|
.Should().Be("shoc-backend@" + canonicalSha);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveRelease_NormalizesUppercaseCommitShaToLowercase()
|
||||||
|
{
|
||||||
|
var canonicalSha = UpperSha.ToLowerInvariant();
|
||||||
|
|
||||||
|
SentryObservability.ResolveRelease("shoc-backend@" + UpperSha)
|
||||||
|
.Should().Be("shoc-backend@" + canonicalSha);
|
||||||
|
SentryObservability.ResolveCommitSha("shoc-backend@" + UpperSha)
|
||||||
|
.Should().Be(canonicalSha);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -39,6 +83,28 @@ public class SentryObservabilityTests
|
||||||
{
|
{
|
||||||
var release = SentryObservability.ResolveRelease("shoc-backend@" + ValidSha);
|
var release = SentryObservability.ResolveRelease("shoc-backend@" + ValidSha);
|
||||||
release[(SentryObservability.ServiceName.Length + 1)..].Should().Be(ValidSha);
|
release[(SentryObservability.ServiceName.Length + 1)..].Should().Be(ValidSha);
|
||||||
|
SentryObservability.ResolveCommitSha("shoc-backend@" + ValidSha)
|
||||||
|
.Should().Be(ValidSha);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveRelease_AndCommitSha_FromNonReleaseAssembly_FallBackSafely()
|
||||||
|
{
|
||||||
|
var assembly = typeof(SentryObservabilityTests).Assembly;
|
||||||
|
|
||||||
|
SentryObservability.ResolveRelease(assembly)
|
||||||
|
.Should().Be(SentryObservability.LocalDevelopmentRelease);
|
||||||
|
SentryObservability.ResolveCommitSha(assembly)
|
||||||
|
.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveRelease_AndCommitSha_FromNullAssembly_FallBackSafely()
|
||||||
|
{
|
||||||
|
SentryObservability.ResolveRelease((Assembly?)null)
|
||||||
|
.Should().Be(SentryObservability.LocalDevelopmentRelease);
|
||||||
|
SentryObservability.ResolveCommitSha((Assembly?)null)
|
||||||
|
.Should().BeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -29,21 +29,46 @@ public static class SentryObservability
|
||||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
|
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
|
||||||
.InformationalVersion;
|
.InformationalVersion;
|
||||||
|
|
||||||
return IsReleaseInformationalVersion(informationalVersion)
|
return ResolveCommitSha(informationalVersion);
|
||||||
? informationalVersion![ReleasePrefix.Length..]
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ResolveRelease(string? informationalVersion) =>
|
public static string ResolveRelease(string? informationalVersion) =>
|
||||||
IsReleaseInformationalVersion(informationalVersion)
|
TryResolveCommitSha(informationalVersion, out var commitSha)
|
||||||
? informationalVersion!
|
? ReleasePrefix + commitSha
|
||||||
: LocalDevelopmentRelease;
|
: LocalDevelopmentRelease;
|
||||||
|
|
||||||
|
public static string? ResolveCommitSha(string? informationalVersion) =>
|
||||||
|
TryResolveCommitSha(informationalVersion, out var commitSha)
|
||||||
|
? commitSha
|
||||||
|
: null;
|
||||||
|
|
||||||
public static bool IsReleaseInformationalVersion(string? value) =>
|
public static bool IsReleaseInformationalVersion(string? value) =>
|
||||||
value is not null
|
TryResolveCommitSha(value, out _);
|
||||||
&& value.StartsWith(ReleasePrefix, StringComparison.Ordinal)
|
|
||||||
&& value.Length == ReleasePrefix.Length + CommitShaLength
|
private static bool TryResolveCommitSha(string? value, out string? commitSha)
|
||||||
&& value[ReleasePrefix.Length..].All(c => c is >= '0' and <= '9' or >= 'a' and <= 'f' or >= 'A' and <= 'F');
|
{
|
||||||
|
commitSha = null;
|
||||||
|
|
||||||
|
if (value is null || !value.StartsWith(ReleasePrefix, StringComparison.Ordinal))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var body = value[ReleasePrefix.Length..];
|
||||||
|
var suffixSeparatorIndex = body.IndexOf('+');
|
||||||
|
var sha = suffixSeparatorIndex < 0 ? body : body[..suffixSeparatorIndex];
|
||||||
|
|
||||||
|
if (sha.Length != CommitShaLength || !sha.All(IsCommitShaHexDigit))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (suffixSeparatorIndex >= 0
|
||||||
|
&& !string.Equals(body[(suffixSeparatorIndex + 1)..], sha, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
commitSha = sha.ToLowerInvariant();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsCommitShaHexDigit(char c) =>
|
||||||
|
c is >= '0' and <= '9' or >= 'a' and <= 'f' or >= 'A' and <= 'F';
|
||||||
|
|
||||||
public static void ConfigureRequest(IHub hub, HttpContext context)
|
public static void ConfigureRequest(IHub hub, HttpContext context)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,14 @@ route values, query strings, or identity claims.
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
1. **Release identity.** `SentryObservability.ResolveRelease(Assembly)` accepts an
|
1. **Release identity.** `SentryObservability.ResolveRelease(Assembly)` accepts an
|
||||||
informational version shaped `shoc-backend@<40 hex commit sha>` and otherwise
|
informational version shaped `shoc-backend@<40 hex commit sha>`, tolerates the
|
||||||
resolves to `local-development`. `scripts/package-elastic-beanstalk.sh` resolves
|
.NET SDK's matching `+<same sha>` suffix for compatibility, canonicalizes the
|
||||||
|
result to lowercase, and otherwise resolves to `local-development`.
|
||||||
|
`scripts/package-elastic-beanstalk.sh` resolves
|
||||||
the commit from `APP_COMMIT_SHA` → `GITHUB_SHA` → `git rev-parse HEAD`, fails
|
the commit from `APP_COMMIT_SHA` → `GITHUB_SHA` → `git rev-parse HEAD`, fails
|
||||||
when `CI=true` cannot produce a valid 40-hex sha, and publishes with
|
when `CI=true` cannot produce a valid 40-hex sha, and publishes with
|
||||||
`-p:SourceRevisionId`, `-p:InformationalVersion=shoc-backend@<sha>`,
|
`-p:SourceRevisionId`, `-p:InformationalVersion=shoc-backend@<sha>`,
|
||||||
|
`-p:IncludeSourceRevisionInInformationalVersion=false`,
|
||||||
`-p:DebugType=portable`, `-p:DebugSymbols=true`.
|
`-p:DebugType=portable`, `-p:DebugSymbols=true`.
|
||||||
2. **Default tags.** `service=shoc-backend` and `app.commit=<sha | local-development>`
|
2. **Default tags.** `service=shoc-backend` and `app.commit=<sha | local-development>`
|
||||||
on `SentryOptions.DefaultTags`. All events use the same commit-addressed
|
on `SentryOptions.DefaultTags`. All events use the same commit-addressed
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ log "publish $API_PROJECT (Release, self-contained, $RUNTIME)"
|
||||||
-p:UseAppHost=true \
|
-p:UseAppHost=true \
|
||||||
-p:SourceRevisionId="$COMMIT_SHA" \
|
-p:SourceRevisionId="$COMMIT_SHA" \
|
||||||
-p:InformationalVersion="shoc-backend@$COMMIT_SHA" \
|
-p:InformationalVersion="shoc-backend@$COMMIT_SHA" \
|
||||||
|
-p:IncludeSourceRevisionInInformationalVersion=false \
|
||||||
-p:DebugType=portable \
|
-p:DebugType=portable \
|
||||||
-p:DebugSymbols=true
|
-p:DebugSymbols=true
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue