Re-organizing templates (#1793)

* templates - re-organized folders

* this seems to work

* move templates to bff and identity server folders

* move templates

* setup build

* correct tags

* aligned tags

* add templates to aspire

* fix sample with clientsecret

* cleanup

* rename SystemDescription to Product

* fix occasionally failing test in integration tests

* write traces to artifacts

* support the 'old' template name as well

* renamed inner 'templates' folder to src

* aligned publish of templates with foss

* templates build

* implemented build script

* moved over quickstart UI

* templates now work

* updated build program
This commit is contained in:
Erwin van der Valk 2025-02-20 14:14:31 +01:00 committed by GitHub
parent 04951cc9f8
commit edc52a121d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
600 changed files with 59518 additions and 472 deletions

View file

@ -7,27 +7,29 @@ using static GitHubContexts;
var contexts = Instance;
{
SystemDescription identityServer = new("identity-server", "identity-server.slnf", "is");
Product identityServer = new("identity-server", "identity-server.slnf", "is");
GenerateIdentityServerWorkflow(identityServer);
GenerateIdentityServerReleaseWorkflow(identityServer);
GenerateCodeQlWorkflow(identityServer, "38 15 * * 0");
}
{
SystemDescription bff = new("bff", "bff.slnf", "bff");
Product bff = new("bff", "bff.slnf", "bff");
GenerateBffWorkflow(bff);
GenerateBffReleaseWorkflow(bff);
GenerateCodeQlWorkflow(bff, "38 16 * * 0");
}
GenerateTemplatesReleaseWorkflow(new Product("templates", "../artifacts/templates.csproj", "templates"));
void GenerateIdentityServerWorkflow(SystemDescription system)
void GenerateIdentityServerWorkflow(Product product)
{
var workflow = new Workflow($"{system.Name}/ci");
var workflow = new Workflow($"{product.Name}/ci");
var paths = new[]
{
$".github/workflows/{system.Name}-**",
$"{system.Name}/**",
$".github/workflows/{product.Name}-**",
$"{product.Name}/**",
"Directory.Packages.props"
};
@ -47,7 +49,7 @@ void GenerateIdentityServerWorkflow(SystemDescription system)
.RunEitherOnBranchOrAsPR()
.Name("Build")
.RunsOn(GitHubHostedRunners.UbuntuLatest)
.Defaults().Run("bash", system.Name)
.Defaults().Run("bash", product.Name)
.Job;
job.Permissions(
@ -63,26 +65,26 @@ void GenerateIdentityServerWorkflow(SystemDescription system)
job.StepSetupDotNet();
job.StepBuild(system.Solution);
job.StepBuild(product.Solution);
job.StepTest(system.Solution);
job.StepTest(product.Solution);
job.StepToolRestore();
job.StepPackSolution(system.Solution);
job.StepPack(product.Solution);
job.StepSign();
job.StepPushToGithub(contexts);
job.StepUploadArtifacts(system.Name);
job.StepUploadArtifacts(product.Name);
var fileName = $"{system.Name}-ci";
var fileName = $"{product.Name}-ci";
WriteWorkflow(workflow, fileName);
}
void GenerateIdentityServerReleaseWorkflow(SystemDescription system)
void GenerateIdentityServerReleaseWorkflow(Product product)
{
var workflow = new Workflow($"{system.Name}/release");
var workflow = new Workflow($"{product.Name}/release");
workflow.On
.WorkflowDispatch()
@ -95,15 +97,15 @@ void GenerateIdentityServerReleaseWorkflow(SystemDescription system)
.Name("Tag and Pack")
.RunsOn(GitHubHostedRunners.UbuntuLatest)
.Permissions(contents: Permission.Write, packages: Permission.Write)
.Defaults().Run("bash", system.Name).Job;
.Defaults().Run("bash", product.Name).Job;
job.Step()
.ActionsCheckout();
job.StepGitCheckoutCustomBranch();
job.StepGitConfig();
job.StepGitRemoveExistingTagIfConfigured(system, contexts);
job.StepGitPushTag(system, contexts);
job.StepGitRemoveExistingTagIfConfigured(product, contexts);
job.StepGitPushTag(product, contexts);
job.StepSetupDotNet();
@ -111,10 +113,10 @@ void GenerateIdentityServerReleaseWorkflow(SystemDescription system)
.Name("Git tag")
.Run($@"git config --global user.email ""github-bot@duendesoftware.com""
git config --global user.name ""Duende Software GitHub Bot""
git tag -a {system.TagPrefix}-{contexts.Event.Input.Version} -m ""Release v{contexts.Event.Input.Version}""
git push origin {system.TagPrefix}-{contexts.Event.Input.Version}");
git tag -a {product.TagPrefix}-{contexts.Event.Input.Version} -m ""Release v{contexts.Event.Input.Version}""
git push origin {product.TagPrefix}-{contexts.Event.Input.Version}");
job.StepPackSolution(system.Solution);
job.StepPack(product.Solution);
job.StepToolRestore();
@ -122,7 +124,7 @@ git push origin {system.TagPrefix}-{contexts.Event.Input.Version}");
job.StepPushToGithub(contexts, pushAlways: true);
job.StepUploadArtifacts(system.Name, uploadAlways: true);
job.StepUploadArtifacts(product.Name, uploadAlways: true);
var publishJob = workflow.Job("publish")
.Name("Publish to nuget.org")
@ -143,17 +145,17 @@ git push origin {system.TagPrefix}-{contexts.Event.Input.Version}");
publishJob.StepPushToNuget(pushAlways: true);
var fileName = $"{system.Name}-release";
var fileName = $"{product.Name}-release";
WriteWorkflow(workflow, fileName);
}
void GenerateBffWorkflow(SystemDescription system)
void GenerateBffWorkflow(Product product)
{
var workflow = new Workflow($"{system.Name}/ci");
var workflow = new Workflow($"{product.Name}/ci");
var paths = new[]
{
$".github/workflows/{system.Name}-**",
$"{system.Name}/**",
$".github/workflows/{product.Name}-**",
$"{product.Name}/**",
"Directory.Packages.props"
};
@ -173,7 +175,7 @@ void GenerateBffWorkflow(SystemDescription system)
.RunEitherOnBranchOrAsPR()
.Name("Build")
.RunsOn(GitHubHostedRunners.UbuntuLatest)
.Defaults().Run("bash", system.Name)
.Defaults().Run("bash", product.Name)
.Job;
job.Permissions(
@ -189,31 +191,33 @@ void GenerateBffWorkflow(SystemDescription system)
job.StepSetupDotNet();
job.StepBuild(system.Solution);
job.StepBuild(product.Solution);
// Devcerts are needed because some tests run start an a http server with https.
job.StepDotNetDevCerts();
job.StepInstallPlayWright();
job.StepTest(system.Solution);
job.StepTest(product.Solution);
job.StepUploadPlaywrightTestTraces(product.Name);
job.StepToolRestore();
job.StepPackSolution(system.Solution);
job.StepPack(product.Solution);
job.StepSign();
job.StepPushToGithub(contexts);
job.StepUploadArtifacts(system.Name);
job.StepUploadArtifacts(product.Name);
var fileName = $"{system.Name}-ci";
var fileName = $"{product.Name}-ci";
WriteWorkflow(workflow, fileName);
}
void GenerateBffReleaseWorkflow(SystemDescription system)
void GenerateBffReleaseWorkflow(Product product)
{
var workflow = new Workflow($"{system.Name}/release");
var workflow = new Workflow($"{product.Name}/release");
workflow.On
.WorkflowDispatch()
@ -226,20 +230,19 @@ void GenerateBffReleaseWorkflow(SystemDescription system)
.Name("Tag and Pack")
.RunsOn(GitHubHostedRunners.UbuntuLatest)
.Permissions(contents: Permission.Write, packages: Permission.Write)
.Defaults().Run("bash", system.Name).Job;
.Defaults().Run("bash", product.Name).Job;
job.Step()
.ActionsCheckout();
job.StepGitCheckoutCustomBranch();
job.StepGitConfig();
job.StepGitRemoveExistingTagIfConfigured(system, contexts);
job.StepGitPushTag(system, contexts);
job.StepGitRemoveExistingTagIfConfigured(product, contexts);
job.StepGitPushTag(product, contexts);
job.StepSetupDotNet();
job.StepPackSolution(system.Solution);
job.StepPack(product.Solution);
job.StepToolRestore();
@ -247,7 +250,7 @@ void GenerateBffReleaseWorkflow(SystemDescription system)
job.StepPushToGithub(contexts, pushAlways: true);
job.StepUploadArtifacts(system.Name, uploadAlways: true);
job.StepUploadArtifacts(product.Name, uploadAlways: true);
var publishJob = workflow.Job("publish")
.Name("Publish to nuget.org")
@ -268,11 +271,11 @@ void GenerateBffReleaseWorkflow(SystemDescription system)
publishJob.StepPushToNuget(pushAlways: true);
var fileName = $"{system.Name}-release";
var fileName = $"{product.Name}-release";
WriteWorkflow(workflow, fileName);
}
void GenerateCodeQlWorkflow(SystemDescription system, string cronSchedule)
void GenerateCodeQlWorkflow(Product system, string cronSchedule)
{
var workflow = new Workflow($"{system.Name}/codeql");
var branches = new[] { "main" };
@ -315,6 +318,67 @@ void GenerateCodeQlWorkflow(SystemDescription system, string cronSchedule)
WriteWorkflow(workflow, fileName);
}
void GenerateTemplatesReleaseWorkflow(Product product)
{
var workflow = new Workflow($"{product.Name}/release");
workflow.On
.WorkflowDispatch()
.Inputs(new StringInput("version", "Version in format X.Y.Z or X.Y.Z-preview.", true, "0.0.0"));
workflow.EnvDefaults();
var job = workflow
.Job("tag")
.Name("Tag and Pack")
.RunsOn(GitHubHostedRunners.UbuntuLatest)
.Permissions(contents: Permission.Write, packages: Permission.Write)
.Defaults().Run("bash", product.Name).Job;
job.Step()
.ActionsCheckout();
job.StepSetupDotNet();
job.StepGitCheckoutCustomBranch();
job.StepGitConfig();
job.StepGitRemoveExistingTagIfConfigured(product, contexts);
job.StepGitPushTag(product, contexts);
job.Step()
.Name("build templates")
.Run("dotnet run --project build");
job.StepToolRestore();
job.StepSign(always: true);
job.StepPushToGithub(contexts, pushAlways: true);
job.StepUploadArtifacts(product.Name, uploadAlways: true);
var publishJob = workflow.Job("publish")
.Name("Publish to nuget.org")
.RunsOn(GitHubHostedRunners.UbuntuLatest)
.Needs("tag")
.Environment("nuget.org", "");
publishJob.Step()
.Uses("actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16") // 4.1.8
.With(("name", "artifacts"), ("path", "artifacts"));
publishJob.StepSetupDotNet();
publishJob.Step()
.Name("List files")
.Shell("bash")
.Run("tree");
publishJob.StepPushToNuget(pushAlways: true);
var fileName = $"{product.Name}-release";
WriteWorkflow(workflow, fileName);
}
void WriteWorkflow(Workflow workflow, string fileName)
{
@ -323,7 +387,9 @@ void WriteWorkflow(Workflow workflow, string fileName)
Console.WriteLine($"Wrote workflow to {filePath}");
}
record SystemDescription(string Name, string Solution, string TagPrefix);
record Product(string Name, string Solution, string TagPrefix)
{
}
public static class StepExtensions
{
@ -365,11 +431,11 @@ public static class StepExtensions
.Name("Tool restore")
.Run("dotnet tool restore");
public static void StepPackSolution(this Job job, string solution)
public static void StepPack(this Job job, string target)
{
job.Step()
.Name($"Pack {solution}")
.Run($"dotnet pack -c Release {solution} -o artifacts");
.Name($"Pack {target}")
.Run($"dotnet pack -c Release {target} -o artifacts");
}
public static Step StepBuild(this Job job, string solution)
@ -462,7 +528,7 @@ public static class StepExtensions
git config --global user.name "Duende Software GitHub Bot"
""");
}
internal static Step StepGitRemoveExistingTagIfConfigured(this Job job, SystemDescription component, GitHubContexts contexts)
internal static Step StepGitRemoveExistingTagIfConfigured(this Job job, Product component, GitHubContexts contexts)
{
return job.Step()
.Name("Git Config")
@ -476,7 +542,7 @@ public static class StepExtensions
fi
""");
}
internal static Step StepGitPushTag(this Job job, SystemDescription component, GitHubContexts contexts)
internal static Step StepGitPushTag(this Job job, Product component, GitHubContexts contexts)
{
return job.Step()
.Name("Git Config")
@ -494,6 +560,21 @@ public static class StepExtensions
new BooleanInput("remove-tag-if-exists", "If set, will remove the existing tag. Use this if you have issues with the previous release action", false, false));
}
public static Step StepUploadPlaywrightTestTraces(this Job job, string componentName)
{
var path = $"{componentName}/test/**/playwright-traces/*.zip";
return job.Step()
.Name("Upload playwright traces")
.If("success() || failure()")
.Uses("actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882") // 4.4.3
.With(
("name", "playwright-traces"),
("path", path),
("overwrite", "true"),
("retention-days", "15"));
}
public static void StepUploadArtifacts(this Job job, string componentName, bool uploadAlways = false)
{
var path = $"{componentName}/artifacts/*.nupkg";

View file

@ -60,6 +60,14 @@ jobs:
reporter: dotnet-trx
fail-on-error: true
fail-on-empty: true
- name: Upload playwright traces
if: success() || failure()
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: playwright-traces
path: bff/test/**/playwright-traces/*.zip
overwrite: true
retention-days: 15
- name: Tool restore
run: dotnet tool restore
- name: Pack bff.slnf

View file

@ -0,0 +1,102 @@
# This was generated by tool. Edits will be overwritten.
name: bff/templates/release
on:
workflow_dispatch:
inputs:
version:
description: 'Version in format X.Y.Z or X.Y.Z-preview.'
type: string
required: true
default: '0.0.0'
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
jobs:
tag:
name: Tag and Pack
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
defaults:
run:
shell: bash
working-directory: bff
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Dotnet
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
dotnet-version: |-
6.0.x
8.0.x
9.0.x
- name: Checkout target branch
if: github.event.inputs.branch != 'main'
run: git checkout ${{ github.event.inputs.branch }}
- name: Git Config
run: |-
git config --global user.email "github-bot@duendesoftware.com"
git config --global user.name "Duende Software GitHub Bot"
- name: Git Config
if: github.event.inputs['remove-tag-if-exists'] == 'true'
run: |-
if git rev-parse bff-${{ github.event.inputs.version }} >/dev/null 2>&1; then
git tag -d bff-${{ github.event.inputs.version }}
git push --delete origin bff-${{ github.event.inputs.version }}
else
echo 'Tag bff-${{ github.event.inputs.version }} does not exist.'
fi
- name: Git Config
run: |-
git tag -a bff-${{ github.event.inputs.version }} -m ""Release v${{ github.event.inputs.version }}""
git push origin bff-${{ github.event.inputs.version }}
- name: Pack templates/templates.bff.csproj
run: dotnet pack -c Release templates/templates.bff.csproj -o artifacts
- name: Tool restore
run: dotnet tool restore
- name: Sign packages
run: |-
for file in artifacts/*.nupkg; do
dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning
done
- name: Push packages to GitHub
run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: artifacts
path: bff/artifacts/*.nupkg
overwrite: true
retention-days: 15
publish:
name: Publish to nuget.org
needs:
- tag
runs-on: ubuntu-latest
environment:
name: nuget.org
steps:
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: artifacts
path: artifacts
- name: Setup Dotnet
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
dotnet-version: |-
6.0.x
8.0.x
9.0.x
- name: List files
run: tree
shell: bash
- name: Push packages to nuget.org
run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate

View file

@ -0,0 +1,102 @@
# This was generated by tool. Edits will be overwritten.
name: identity-server/templates/release
on:
workflow_dispatch:
inputs:
version:
description: 'Version in format X.Y.Z or X.Y.Z-preview.'
type: string
required: true
default: '0.0.0'
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
jobs:
tag:
name: Tag and Pack
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
defaults:
run:
shell: bash
working-directory: identity-server
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Dotnet
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
dotnet-version: |-
6.0.x
8.0.x
9.0.x
- name: Checkout target branch
if: github.event.inputs.branch != 'main'
run: git checkout ${{ github.event.inputs.branch }}
- name: Git Config
run: |-
git config --global user.email "github-bot@duendesoftware.com"
git config --global user.name "Duende Software GitHub Bot"
- name: Git Config
if: github.event.inputs['remove-tag-if-exists'] == 'true'
run: |-
if git rev-parse is-${{ github.event.inputs.version }} >/dev/null 2>&1; then
git tag -d is-${{ github.event.inputs.version }}
git push --delete origin is-${{ github.event.inputs.version }}
else
echo 'Tag is-${{ github.event.inputs.version }} does not exist.'
fi
- name: Git Config
run: |-
git tag -a is-${{ github.event.inputs.version }} -m ""Release v${{ github.event.inputs.version }}""
git push origin is-${{ github.event.inputs.version }}
- name: Pack templates/templates.identity-server.csproj
run: dotnet pack -c Release templates/templates.identity-server.csproj -o artifacts
- name: Tool restore
run: dotnet tool restore
- name: Sign packages
run: |-
for file in artifacts/*.nupkg; do
dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning
done
- name: Push packages to GitHub
run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: artifacts
path: identity-server/artifacts/*.nupkg
overwrite: true
retention-days: 15
publish:
name: Publish to nuget.org
needs:
- tag
runs-on: ubuntu-latest
environment:
name: nuget.org
steps:
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: artifacts
path: artifacts
- name: Setup Dotnet
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
dotnet-version: |-
6.0.x
8.0.x
9.0.x
- name: List files
run: tree
shell: bash
- name: Push packages to nuget.org
run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate

View file

@ -1,43 +0,0 @@
name: "templates-ci"
on:
push:
branches:
- main
paths:
- 'templates/**'
pull_request:
branches:
- main
paths:
- 'templates/**'
env:
DOTNET_NOLOGO: true
jobs:
build:
strategy:
fail-fast: false
matrix:
runs-on: [windows-latest]
name: ${{ matrix.runs-on }}
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup dotnet (main)
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- run: dotnet --info
- if: (matrix.runs-on == 'windows-latest') && (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/'))
env:
SignClientSecret: ${{ secrets.SIGNCLIENTSECRET }}
run: |
./build.ps1
dotnet nuget push .\artifacts\*.nupkg -s https://www.myget.org/F/duende_identityserver/api/v2/package -k ${{ secrets.MYGET }}

102
.github/workflows/templates-release.yml vendored Normal file
View file

@ -0,0 +1,102 @@
# This was generated by tool. Edits will be overwritten.
name: templates/release
on:
workflow_dispatch:
inputs:
version:
description: 'Version in format X.Y.Z or X.Y.Z-preview.'
type: string
required: true
default: '0.0.0'
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
jobs:
tag:
name: Tag and Pack
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
defaults:
run:
shell: bash
working-directory: templates
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Dotnet
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
dotnet-version: |-
6.0.x
8.0.x
9.0.x
- name: Checkout target branch
if: github.event.inputs.branch != 'main'
run: git checkout ${{ github.event.inputs.branch }}
- name: Git Config
run: |-
git config --global user.email "github-bot@duendesoftware.com"
git config --global user.name "Duende Software GitHub Bot"
- name: Git Config
if: github.event.inputs['remove-tag-if-exists'] == 'true'
run: |-
if git rev-parse templates-${{ github.event.inputs.version }} >/dev/null 2>&1; then
git tag -d templates-${{ github.event.inputs.version }}
git push --delete origin templates-${{ github.event.inputs.version }}
else
echo 'Tag templates-${{ github.event.inputs.version }} does not exist.'
fi
- name: Git Config
run: |-
git tag -a templates-${{ github.event.inputs.version }} -m ""Release v${{ github.event.inputs.version }}""
git push origin templates-${{ github.event.inputs.version }}
- name: build templates
run: dotnet run --project build
- name: Tool restore
run: dotnet tool restore
- name: Sign packages
run: |-
for file in artifacts/*.nupkg; do
dotnet NuGetKeyVaultSignTool sign "$file" --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-url https://duendecodesigninghsm.vault.azure.net/ --azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 --azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 --azure-key-vault-client-secret ${{ secrets.SignClientSecret }} --azure-key-vault-certificate NuGetPackageSigning
done
- name: Push packages to GitHub
run: dotnet nuget push artifacts/*.nupkg --source https://nuget.pkg.github.com/DuendeSoftware/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: artifacts
path: templates/artifacts/*.nupkg
overwrite: true
retention-days: 15
publish:
name: Publish to nuget.org
needs:
- tag
runs-on: ubuntu-latest
environment:
name: nuget.org
steps:
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: artifacts
path: artifacts
- name: Setup Dotnet
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
dotnet-version: |-
6.0.x
8.0.x
9.0.x
- name: List files
run: tree
shell: bash
- name: Push packages to nuget.org
run: dotnet nuget push artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ORG_API_KEY }} --skip-duplicate

5
.gitignore vendored
View file

@ -218,4 +218,7 @@ tempkey.jwk
keys
*.key
test/Configuration.IntegrationTests/CoverageReports
nCrunchTemp_*
nCrunchTemp_*
playwright-traces
artifacts

View file

@ -22,6 +22,8 @@
"bff\\src\\Bff.EntityFramework\\Bff.EntityFramework.csproj",
"bff\\src\\Bff.Yarp\\Bff.Yarp.csproj",
"bff\\src\\Bff\\Bff.csproj",
"bff\\templates\\src\\BffLocalApi\\BffLocalApi.csproj",
"bff\\templates\\src\\BffRemoteApi\\BffRemoteApi.csproj",
"bff\\test\\Bff.Blazor.Client.UnitTests\\Bff.Blazor.Client.UnitTests.csproj",
"bff\\test\\Bff.Blazor.UnitTests\\Bff.Blazor.UnitTests.csproj",
"bff\\test\\Bff.EntityFramework.Tests\\Bff.EntityFramework.Tests.csproj",

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />
@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost"/>
<PackageReference Include="Aspire.Hosting.AppHost" />
</ItemGroup>
<ItemGroup>
@ -32,6 +32,11 @@
<ProjectReference Include="..\Blazor\WebAssembly\Hosts.Bff.Blazor.WebAssembly.Client\Hosts.Bff.Blazor.WebAssembly.Client.csproj" />
<ProjectReference Include="..\Blazor\WebAssembly\Hosts.Bff.Blazor.WebAssembly\Hosts.Bff.Blazor.WebAssembly.csproj" />
<ProjectReference Include="..\Hosts.IdentityServer\Hosts.IdentityServer.csproj" />
<ProjectReference Include="..\..\templates\src\BffLocalApi\BffLocalApi.csproj" />
<ProjectReference Include="..\..\templates\src\BffRemoteApi\BffRemoteApi.csproj" />
</ItemGroup>
</Project>

View file

@ -1,3 +1,4 @@
using Aspire.Hosting;
using Hosts.ServiceDefaults;
using Projects;
@ -49,8 +50,13 @@ idServer
.WithReference(bffBlazorPerComponent)
.WithReference(bffBlazorWebAssembly)
.WithReference(apiDPop)
.WithReference(bffDPop)
;
.WithReference(bffDPop);
builder.AddProject<BffLocalApi>("templates-bff-local", launchProfileName: null)
.WithHttpsEndpoint(5300, name: "bff-local");
builder.AddProject<BffRemoteApi>("templates-bff-remote", launchProfileName: null)
.WithHttpsEndpoint(5310, name: "bff-remote");
builder.Build().Run();

View file

@ -2,12 +2,13 @@
"author": "Duende Software",
"classifications": [
"Web",
"IdentityServer"
"Duende",
"BFF"
],
"name": "Duende BFF using a Local API",
"identity": "IdentityServer.BFF.LocalApi",
"groupIdentity": "IdentityServer.BFF.LocalApi",
"shortName": "bff-localapi",
"identity": "Duende.BFF.LocalApi",
"groupIdentity": "Duende.BFF.LocalApi",
"shortName": "duende-bff-localapi",
"tags": {
"language": "C#",
"type": "project"

View file

@ -2,12 +2,13 @@
"author": "Duende Software",
"classifications": [
"Web",
"IdentityServer"
"Duende",
"BFF"
],
"name": "Duende BFF Host using a Remote API",
"identity": "IdentityServer.BFF.RemoteApi",
"groupIdentity": "IdentityServer.BFF.RemoteApi",
"shortName": "bff-remoteapi",
"identity": "Duende.BFF.RemoteApi",
"groupIdentity": "Duende.BFF.RemoteApi",
"shortName": "duende-bff-remoteapi",
"tags": {
"language": "C#",
"type": "project"
@ -20,4 +21,3 @@
}
]
}
}

View file

@ -10,7 +10,7 @@
"BFF": {
"Authority": "https://demo.duendesoftware.com",
"ClientId": "interactive.confidential",
"ClientSecret": "secret",
"Scopes": [ "openid", "profile", "api", "offline_access" ],
"Apis": [

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<IsPackable>false</IsPackable>
</PropertyGroup>
</Project>

View file

@ -1,14 +1,10 @@
using Microsoft.Playwright;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Playwright;
namespace Hosts.Tests.PageModels;
public class PerComponentPageModel : BlazorModel
{
protected override async Task Verify()
{
(await Page.TitleAsync()).ShouldBe("Home");
}
public async Task<WebAssemblyPageModel> LogOut()
{
// Log out again
@ -28,6 +24,11 @@ public class PerComponentPageModel : BlazorModel
public class CallApiPageModel : PerComponentPageModel
{
protected override async Task Verify()
{
await Expect(Page.GetByText("InteractiveServer")).ToBeVisibleAsync();
}
public async Task InvokeCallApi(string headingName)
{
// Get the heading with the name "InteractiveServer"

View file

@ -4,10 +4,13 @@
using Hosts.Tests.TestInfra;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
using System.Reflection;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Hosts.Tests;
[WithTestName]
[Collection(AppHostCollection.CollectionName)]
public class PlaywrightTestBase : PageTest, IDisposable
{
@ -33,6 +36,41 @@ public class PlaywrightTestBase : PageTest, IDisposable
}
}
public override async Task InitializeAsync()
{
await base.InitializeAsync();
Context.SetDefaultTimeout(10_000);
await Context.Tracing.StartAsync(new()
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
public override async Task DisposeAsync()
{
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Environment.CurrentDirectory;
// if path ends with /bin/{build configuration}/{dotnetversion}, then strip that from the path.
var bin = Path.GetFullPath(Path.Combine(path, "../../"));
if (bin.EndsWith("\\bin\\") || bin.EndsWith("/bin/"))
{
path = Path.GetFullPath(Path.Combine(path, "../../../"));
}
await Context.Tracing.StopAsync(new()
{
Path = Path.Combine(
path,
"playwright-traces",
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
)
});
await base.DisposeAsync();
}
public override BrowserNewContextOptions ContextOptions()
{
return new()
@ -44,7 +82,6 @@ public class PlaywrightTestBase : PageTest, IDisposable
// Even though we use dotnet dev-certs https --trust on the build agent,
// it still claims the certs are invalid.
IgnoreHTTPSErrors = true,
};
}
@ -73,4 +110,20 @@ public class PlaywrightTestBase : PageTest, IDisposable
{
return Fixture.CreateHttpClient(clientName);
}
}
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string.Empty;
public static string CurrentClassName = string.Empty;
public override void Before(MethodInfo methodInfo)
{
CurrentTestName = methodInfo.Name;
CurrentClassName = methodInfo.DeclaringType!.Name;
}
public override void After(MethodInfo methodInfo)
{
}
}

View file

@ -15,6 +15,10 @@
"identity-server\\src\\EntityFramework\\Duende.IdentityServer.EntityFramework.csproj",
"identity-server\\src\\IdentityServer\\Duende.IdentityServer.csproj",
"identity-server\\src\\Storage\\Duende.IdentityServer.Storage.csproj",
"identity-server\\templates\\src\\IdentityServerAspNetIdentity\\IdentityServerAspNetIdentity.csproj",
"identity-server\\templates\\src\\IdentityServerEmpty\\IdentityServerEmpty.csproj",
"identity-server\\templates\\src\\IdentityServerEntityFramework\\IdentityServerEntityFramework.csproj",
"identity-server\\templates\\src\\IdentityServerInMem\\IdentityServerInMem.csproj",
"identity-server\\test\\Configuration.IntegrationTests\\Configuration.IntegrationTests.csproj",
"identity-server\\test\\EntityFramework.IntegrationTests\\EntityFramework.IntegrationTests.csproj",
"identity-server\\test\\EntityFramework.Storage.IntegrationTests\\EntityFramework.Storage.IntegrationTests.csproj",

View file

@ -0,0 +1,31 @@
# Duende.Templates.IdentityServer
.NET CLI Templates for Duende IdentityServer
### dotnet new is-empty
Creates a minimal Duende IdentityServer project without a UI.
### dotnet new is-inmem
Adds a basic Duende IdentityServer with UI, test users and sample clients and resources.
### dotnet new is-asp-id
Adds a basic Duende IdentityServer that uses ASP.NET Identity for user management. If you automatically seed the database, you will get two users: `alice` and `bob` - both with password `Pass123$`. Check the `SeedData.cs` file.
### dotnet new is-ef
Adds a basic Duende IdentityServer that uses Entity Framework for configuration and state management. If you seed the database, you get a couple of basic client and resource registrations, check the `SeedData.cs` file.
## Installation
Install with:
`dotnet new install Duende.Templates.IdentityServer`
If you need to set back your dotnet new list to "factory defaults", use this command:
`dotnet new --debug:reinit`
If you find that this doesn't work, remove the entries from the file %userprofile%/.templateengine/packages.json
To uninstall the templates, use
`dotnet new uninstall Duende.Templates.IdentityServer`

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<IsPackable>false</IsPackable>
</PropertyGroup>
</Project>

View file

@ -2,12 +2,13 @@
"author": "Duende Software",
"classifications": [
"Web",
"Duende",
"IdentityServer"
],
"name": "Duende IdentityServer with ASP.NET Core Identity",
"identity": "IdentityServer.AspNetIdentity",
"groupIdentity": "IdentityServer.AspNetIdentity",
"shortName": "isaspid",
"identity": "Duende.IdentityServer.AspNetIdentity",
"groupIdentity": "Duende.IdentityServer.AspNetIdentity",
"shortName": ["duende-is-aspid"],
"tags": {
"language": "C#",
"type": "project"

Some files were not shown because too many files have changed in this diff Show more