Skip to content

Adding perpetual licensing#4608

Merged
jbogard merged 7 commits intomainfrom
perpetual
Feb 24, 2026
Merged

Adding perpetual licensing#4608
jbogard merged 7 commits intomainfrom
perpetual

Conversation

@jbogard
Copy link
Contributor

@jbogard jbogard commented Feb 23, 2026

No description provided.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds perpetual licensing support to AutoMapper, allowing licenses to remain valid for builds created before the license expiration date, even after the license has expired. The implementation introduces a build date timestamp that is embedded in the assembly at compile time and checked against the license expiration date during validation.

Changes:

  • Added build date tracking via assembly metadata embedded during compilation
  • Implemented perpetual license claim parsing and validation logic
  • Added comprehensive test coverage for perpetual licensing scenarios

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/AutoMapper/Licensing/BuildInfo.cs New class to extract build date from assembly metadata attributes
src/AutoMapper/AutoMapper.csproj MSBuild target to embed current UTC timestamp as assembly metadata during compilation
src/AutoMapper/Licensing/License.cs Added IsPerpetual property to parse "perpetual" claim from license tokens
src/AutoMapper/Licensing/LicenseValidator.cs Enhanced validation logic to allow expired perpetual licenses when build date precedes expiration
src/UnitTests/Licensing/LicenseValidatorTests.cs Three new test cases covering perpetual license validation scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 64 to 72
<Target Name="EmbedBuildDate" BeforeTargets="CoreCompile">
<PropertyGroup>
<BuildDateUtc>$([System.DateTime]::UtcNow.ToString("O"))</BuildDateUtc>
</PropertyGroup>
<WriteLinesToFile File="$(IntermediateOutputPath)BuildDateGenerated.cs" Lines="[assembly: System.Reflection.AssemblyMetadata(&quot;BuildDateUtc&quot;, &quot;$(BuildDateUtc)&quot;)]" Overwrite="true" />
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)BuildDateGenerated.cs" />
</ItemGroup>
</Target>
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EmbedBuildDate target uses DateTime.UtcNow which makes every build produce a different assembly, conflicting with the Deterministic build setting on line 26. This will break deterministic builds and may cause issues with build caching, reproducible builds, and package signing.

Consider using a source control-based approach (like git commit timestamp) or an environment variable that can be set to a fixed value in CI/CD pipelines while allowing dynamic values for local development builds. For example, you could check for an environment variable first: BuildDateUtc>$([System.Environment]::GetEnvironmentVariable('BUILD_DATE_UTC', 'EnvironmentVariableTarget.Process'))</BuildDateUtc> and only fall back to UtcNow if not set, or use SOURCE_DATE_EPOCH for reproducible builds.

Copilot uses AI. Check for mistakes.
Comment on lines +173 to +199
[Fact]
public void Should_handle_missing_perpetual_claim()
{
var factory = new LoggerFactory();
var provider = new FakeLoggerProvider();
factory.AddProvider(provider);

var licenseValidator = new LicenseValidator(factory);
var license = new License(
new Claim("account_id", Guid.NewGuid().ToString()),
new Claim("customer_id", Guid.NewGuid().ToString()),
new Claim("sub_id", Guid.NewGuid().ToString()),
new Claim("iat", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()),
new Claim("exp", DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeSeconds().ToString()),
new Claim("edition", nameof(Edition.Community)),
new Claim("type", nameof(AutoMapper.Licensing.ProductType.Bundle)));

license.IsConfigured.ShouldBeTrue();
license.IsPerpetual.ShouldBeFalse();

licenseValidator.Validate(license);

var logMessages = provider.Collector.GetSnapshot();
logMessages.ShouldNotContain(log => log.Level == LogLevel.Error
|| log.Level == LogLevel.Warning
|| log.Level == LogLevel.Critical);
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests don't cover the edge case where a perpetual license is used but the build date is unavailable (null). According to the validation logic on line 37 of LicenseValidator.cs, if _buildDate is null, the perpetual license feature won't activate and the expired license will be rejected.

Add a test case that validates an expired perpetual license when no build date is provided (call new LicenseValidator(factory) without passing a buildDate, and ensure BuildInfo.BuildDate returns null in the test context). This should verify that the system gracefully handles this scenario and logs an appropriate error.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

jbogard and others added 3 commits February 24, 2026 10:41
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jbogard jbogard merged commit 6e084d3 into main Feb 24, 2026
6 checks passed
@jbogard jbogard deleted the perpetual branch February 24, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants