diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml
index 130b0217..02847f09 100644
--- a/.github/workflows/build-and-deploy.yml
+++ b/.github/workflows/build-and-deploy.yml
@@ -7,7 +7,7 @@ on:
branches:
- master
env:
- VERSION: 10.0.0-rc1
+ VERSION: 10.0.0
jobs:
build-and-deploy:
runs-on: ubuntu-latest
@@ -28,6 +28,7 @@ jobs:
name: "Release ${{ env.VERSION }}"
body: |
Version: ${{ env.VERSION }}
+ Build run: ${{ github.run_number }}
Commit: ${{ github.sha }}
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ApiClients.Audit/.docker/docker-compose.yml b/Api.ApiClients.Audit/.docker/docker-compose.yml
index 3701e77a..65f425e7 100644
--- a/Api.ApiClients.Audit/.docker/docker-compose.yml
+++ b/Api.ApiClients.Audit/.docker/docker-compose.yml
@@ -16,7 +16,7 @@ services:
hostname: api-apiclients-audit-service
restart: on-failure
ports:
- - 8181:8181
+ - 8181:8080
build:
context: ../Api.ApiClients.Audit.Service
dockerfile: "Dockerfile.Local"
diff --git a/Api.ApiClients.Audit/.github/workflows/build-and-deploy.yml b/Api.ApiClients.Audit/.github/workflows/build-and-deploy.yml
index 2e9dbcea..3d59297e 100644
--- a/Api.ApiClients.Audit/.github/workflows/build-and-deploy.yml
+++ b/Api.ApiClients.Audit/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ApiClients.Audit
IMAGE_NAME: api.apiclients.audit
SERVICE_NAME: api-apiclients-audit
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ApiClients.Audit/.kubernetes/configmap.yaml b/Api.ApiClients.Audit/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ApiClients.Audit/.kubernetes/configmap.yaml
+++ b/Api.ApiClients.Audit/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ApiClients.Audit/.kubernetes/deployment.yaml b/Api.ApiClients.Audit/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ApiClients.Audit/.kubernetes/deployment.yaml
+++ b/Api.ApiClients.Audit/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ApiClients.Audit/Api.ApiClients.Audit.Models/Api.ApiClients.Audit.Models.csproj b/Api.ApiClients.Audit/Api.ApiClients.Audit.Models/Api.ApiClients.Audit.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ApiClients.Audit/Api.ApiClients.Audit.Models/Api.ApiClients.Audit.Models.csproj
+++ b/Api.ApiClients.Audit/Api.ApiClients.Audit.Models/Api.ApiClients.Audit.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients.Audit/Api.ApiClients.Audit.Service.Models/Api.ApiClients.Audit.Service.Models.csproj b/Api.ApiClients.Audit/Api.ApiClients.Audit.Service.Models/Api.ApiClients.Audit.Service.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.ApiClients.Audit/Api.ApiClients.Audit.Service.Models/Api.ApiClients.Audit.Service.Models.csproj
+++ b/Api.ApiClients.Audit/Api.ApiClients.Audit.Service.Models/Api.ApiClients.Audit.Service.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/Dockerfile.Local b/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/Dockerfile.Local
index 1e6d12c6..4310acdb 100644
--- a/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/Dockerfile.Local
+++ b/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.Audit.Service.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/appsettings.json b/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/appsettings.json
index dbd68122..d43a066a 100644
--- a/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/appsettings.json
+++ b/Api.ApiClients.Audit/Api.ApiClients.Audit.Service/appsettings.json
@@ -5,7 +5,7 @@
"Root": "api",
"Http": {
"Ports": [
- 8181
+ 8080
]
}
}
diff --git a/Api.ApiClients.Audit/Api.ApiClients.Audit/Dockerfile.Local b/Api.ApiClients.Audit/Api.ApiClients.Audit/Dockerfile.Local
index f55f6733..383c565c 100644
--- a/Api.ApiClients.Audit/Api.ApiClients.Audit/Dockerfile.Local
+++ b/Api.ApiClients.Audit/Api.ApiClients.Audit/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.Audit.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients.Audit/Dockerfile b/Api.ApiClients.Audit/Dockerfile
index ae5aa0b8..18cc52ae 100644
--- a/Api.ApiClients.Audit/Dockerfile
+++ b/Api.ApiClients.Audit/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ApiClients.Entity/.docker/docker-compose.yml b/Api.ApiClients.Entity/.docker/docker-compose.yml
index c93a17e7..a51b8975 100644
--- a/Api.ApiClients.Entity/.docker/docker-compose.yml
+++ b/Api.ApiClients.Entity/.docker/docker-compose.yml
@@ -16,7 +16,7 @@ services:
hostname: api-apiclients-entity-service
restart: on-failure
ports:
- - 8181:8181
+ - 8181:8080
build:
context: ../Api.ApiClients.Entity.Service
dockerfile: "Dockerfile.Local"
diff --git a/Api.ApiClients.Entity/.github/workflows/build-and-deploy.yml b/Api.ApiClients.Entity/.github/workflows/build-and-deploy.yml
index bec796fc..3aeb1fe2 100644
--- a/Api.ApiClients.Entity/.github/workflows/build-and-deploy.yml
+++ b/Api.ApiClients.Entity/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ApiClients.Entity
IMAGE_NAME: api.apiclients.entity
SERVICE_NAME: api-apiclients-entity
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ApiClients.Entity/.kubernetes/configmap.yaml b/Api.ApiClients.Entity/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ApiClients.Entity/.kubernetes/configmap.yaml
+++ b/Api.ApiClients.Entity/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ApiClients.Entity/.kubernetes/deployment.yaml b/Api.ApiClients.Entity/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ApiClients.Entity/.kubernetes/deployment.yaml
+++ b/Api.ApiClients.Entity/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ApiClients.Entity/Api.ApiClients.Entity.Models/Api.ApiClients.Entity.Models.csproj b/Api.ApiClients.Entity/Api.ApiClients.Entity.Models/Api.ApiClients.Entity.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ApiClients.Entity/Api.ApiClients.Entity.Models/Api.ApiClients.Entity.Models.csproj
+++ b/Api.ApiClients.Entity/Api.ApiClients.Entity.Models/Api.ApiClients.Entity.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients.Entity/Api.ApiClients.Entity.Service.Models/Api.ApiClients.Entity.Service.Models.csproj b/Api.ApiClients.Entity/Api.ApiClients.Entity.Service.Models/Api.ApiClients.Entity.Service.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.ApiClients.Entity/Api.ApiClients.Entity.Service.Models/Api.ApiClients.Entity.Service.Models.csproj
+++ b/Api.ApiClients.Entity/Api.ApiClients.Entity.Service.Models/Api.ApiClients.Entity.Service.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/Dockerfile.Local b/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/Dockerfile.Local
index 9223f500..7ed69ae9 100644
--- a/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/Dockerfile.Local
+++ b/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.Entity.Service.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/appsettings.json b/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/appsettings.json
index dbd68122..d43a066a 100644
--- a/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/appsettings.json
+++ b/Api.ApiClients.Entity/Api.ApiClients.Entity.Service/appsettings.json
@@ -5,7 +5,7 @@
"Root": "api",
"Http": {
"Ports": [
- 8181
+ 8080
]
}
}
diff --git a/Api.ApiClients.Entity/Api.ApiClients.Entity/Dockerfile.Local b/Api.ApiClients.Entity/Api.ApiClients.Entity/Dockerfile.Local
index 72d7216b..3a6a08e0 100644
--- a/Api.ApiClients.Entity/Api.ApiClients.Entity/Dockerfile.Local
+++ b/Api.ApiClients.Entity/Api.ApiClients.Entity/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.Entity.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients.Entity/Api.ApiClients.Entity/appsettings.json b/Api.ApiClients.Entity/Api.ApiClients.Entity/appsettings.json
index 62eb606b..ab7ef06a 100644
--- a/Api.ApiClients.Entity/Api.ApiClients.Entity/appsettings.json
+++ b/Api.ApiClients.Entity/Api.ApiClients.Entity/appsettings.json
@@ -13,7 +13,7 @@
"NanoApiClient": {
"Host": "api.apiclients.entity.service",
"Root": "api",
- "Port": 8181,
+ "Port": 8080,
"UseSsl": false,
"Timeout": "00:00:30",
"HealthCheck": {
diff --git a/Api.ApiClients.Entity/Dockerfile b/Api.ApiClients.Entity/Dockerfile
index 961dbddb..b6bc2925 100644
--- a/Api.ApiClients.Entity/Dockerfile
+++ b/Api.ApiClients.Entity/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ApiClients.RootLogIn/.docker/docker-compose.yml b/Api.ApiClients.RootLogIn/.docker/docker-compose.yml
index 8f0c55a8..accdcd21 100644
--- a/Api.ApiClients.RootLogIn/.docker/docker-compose.yml
+++ b/Api.ApiClients.RootLogIn/.docker/docker-compose.yml
@@ -16,7 +16,7 @@ services:
hostname: api-apiclients-rootlogin-service
restart: on-failure
ports:
- - 8181:8181
+ - 8181:8080
build:
context: ../Api.ApiClients.RootLogIn.Service
dockerfile: "Dockerfile.Local"
diff --git a/Api.ApiClients.RootLogIn/.github/workflows/build-and-deploy.yml b/Api.ApiClients.RootLogIn/.github/workflows/build-and-deploy.yml
index 1fa27e27..e3a91aa2 100644
--- a/Api.ApiClients.RootLogIn/.github/workflows/build-and-deploy.yml
+++ b/Api.ApiClients.RootLogIn/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ApiClients.RootLogIn
IMAGE_NAME: api.apiclients.rootlogin
SERVICE_NAME: api-apiclients-rootlogin
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ApiClients.RootLogIn/.kubernetes/configmap.yaml b/Api.ApiClients.RootLogIn/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ApiClients.RootLogIn/.kubernetes/configmap.yaml
+++ b/Api.ApiClients.RootLogIn/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ApiClients.RootLogIn/.kubernetes/deployment.yaml b/Api.ApiClients.RootLogIn/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ApiClients.RootLogIn/.kubernetes/deployment.yaml
+++ b/Api.ApiClients.RootLogIn/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogIn.Models/Api.ApiClients.RootLogIn.Models.csproj b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogIn.Models/Api.ApiClients.RootLogIn.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogIn.Models/Api.ApiClients.RootLogIn.Models.csproj
+++ b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogIn.Models/Api.ApiClients.RootLogIn.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service.Models/Api.ApiClients.RootLogin.Service.Models.csproj b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service.Models/Api.ApiClients.RootLogin.Service.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service.Models/Api.ApiClients.RootLogin.Service.Models.csproj
+++ b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service.Models/Api.ApiClients.RootLogin.Service.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/Dockerfile.Local b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/Dockerfile.Local
index e6afa324..18c597d8 100644
--- a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/Dockerfile.Local
+++ b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Auth.RootLogin.Service.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/appsettings.json b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/appsettings.json
index f28ebab1..3ecf604f 100644
--- a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/appsettings.json
+++ b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin.Service/appsettings.json
@@ -5,7 +5,7 @@
"Root": "api",
"Http": {
"Ports": [
- 8181
+ 8080
]
}
},
diff --git a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin/Dockerfile.Local b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin/Dockerfile.Local
index 557a434d..e09e773f 100644
--- a/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin/Dockerfile.Local
+++ b/Api.ApiClients.RootLogIn/Api.ApiClients.RootLogin/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.RootLogIn.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients.RootLogIn/Dockerfile b/Api.ApiClients.RootLogIn/Dockerfile
index 2fad135c..f48b44c8 100644
--- a/Api.ApiClients.RootLogIn/Dockerfile
+++ b/Api.ApiClients.RootLogIn/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ApiClients/.docker/docker-compose.yml b/Api.ApiClients/.docker/docker-compose.yml
index 0129b3b3..ab197d18 100644
--- a/Api.ApiClients/.docker/docker-compose.yml
+++ b/Api.ApiClients/.docker/docker-compose.yml
@@ -16,7 +16,7 @@ services:
hostname: api-apiclients-service
restart: on-failure
ports:
- - 8181:8181
+ - 8181:8080
build:
context: ../Api.ApiClients.Service
dockerfile: "Dockerfile.Local"
diff --git a/Api.ApiClients/.github/workflows/build-and-deploy.yml b/Api.ApiClients/.github/workflows/build-and-deploy.yml
index f97c3744..9ba21814 100644
--- a/Api.ApiClients/.github/workflows/build-and-deploy.yml
+++ b/Api.ApiClients/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ApiClients
IMAGE_NAME: api.apiclients
SERVICE_NAME: api-apiclients
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ApiClients/.kubernetes/configmap.yaml b/Api.ApiClients/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ApiClients/.kubernetes/configmap.yaml
+++ b/Api.ApiClients/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ApiClients/.kubernetes/deployment.yaml b/Api.ApiClients/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ApiClients/.kubernetes/deployment.yaml
+++ b/Api.ApiClients/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ApiClients/Api.ApiClients.Models/Api.ApiClients.Models.csproj b/Api.ApiClients/Api.ApiClients.Models/Api.ApiClients.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ApiClients/Api.ApiClients.Models/Api.ApiClients.Models.csproj
+++ b/Api.ApiClients/Api.ApiClients.Models/Api.ApiClients.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients/Api.ApiClients.Service.Models/Api.ApiClients.Service.Models.csproj b/Api.ApiClients/Api.ApiClients.Service.Models/Api.ApiClients.Service.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ApiClients/Api.ApiClients.Service.Models/Api.ApiClients.Service.Models.csproj
+++ b/Api.ApiClients/Api.ApiClients.Service.Models/Api.ApiClients.Service.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ApiClients/Api.ApiClients.Service/Dockerfile.Local b/Api.ApiClients/Api.ApiClients.Service/Dockerfile.Local
index 5d914dde..17025cf0 100644
--- a/Api.ApiClients/Api.ApiClients.Service/Dockerfile.Local
+++ b/Api.ApiClients/Api.ApiClients.Service/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.Service.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients/Api.ApiClients.Service/appsettings.json b/Api.ApiClients/Api.ApiClients.Service/appsettings.json
index 702a5e62..e8d9ff25 100644
--- a/Api.ApiClients/Api.ApiClients.Service/appsettings.json
+++ b/Api.ApiClients/Api.ApiClients.Service/appsettings.json
@@ -5,7 +5,7 @@
"Root": "api",
"Http": {
"Ports": [
- 8181
+ 8080
]
}
}
diff --git a/Api.ApiClients/Api.ApiClients/Dockerfile.Local b/Api.ApiClients/Api.ApiClients/Dockerfile.Local
index ce847262..6ef7cfd1 100644
--- a/Api.ApiClients/Api.ApiClients/Dockerfile.Local
+++ b/Api.ApiClients/Api.ApiClients/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ApiClients.dll"]
\ No newline at end of file
diff --git a/Api.ApiClients/Dockerfile b/Api.ApiClients/Dockerfile
index 554c9c3f..42ba7394 100644
--- a/Api.ApiClients/Dockerfile
+++ b/Api.ApiClients/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ApiClients/README.md b/Api.ApiClients/README.md
index 6e3af283..06f0aced 100644
--- a/Api.ApiClients/README.md
+++ b/Api.ApiClients/README.md
@@ -52,7 +52,7 @@ Configured the application with a connection to the `NanoApiClient`.
"NanoApiClient": {
"Host": "localhost",
"Root": "api",
- "Port": 8181,
+ "Port": 8080,
"UseSsl": false,
"Timeout": "00:00:30",
"HealthCheck": {
diff --git a/Api.Auth.External.Custom/.github/workflows/build-and-deploy.yml b/Api.Auth.External.Custom/.github/workflows/build-and-deploy.yml
index 1b1ae5fa..15b8896d 100644
--- a/Api.Auth.External.Custom/.github/workflows/build-and-deploy.yml
+++ b/Api.Auth.External.Custom/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Auth.External.Custom
IMAGE_NAME: api.auth.external.custom
SERVICE_NAME: api-auth-external-custom
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,22 +34,21 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
- AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
+ AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,68 +61,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -165,7 +159,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -173,6 +167,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Auth.External.Custom/.kubernetes/configmap.yaml b/Api.Auth.External.Custom/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Auth.External.Custom/.kubernetes/configmap.yaml
+++ b/Api.Auth.External.Custom/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Auth.External.Custom/.kubernetes/deployment.yaml b/Api.Auth.External.Custom/.kubernetes/deployment.yaml
index aca5889f..6ea6a615 100644
--- a/Api.Auth.External.Custom/.kubernetes/deployment.yaml
+++ b/Api.Auth.External.Custom/.kubernetes/deployment.yaml
@@ -84,6 +84,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Auth.External.Custom/Api.Auth.External.Custom.Models/Api.Auth.External.Custom.Models.csproj b/Api.Auth.External.Custom/Api.Auth.External.Custom.Models/Api.Auth.External.Custom.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Auth.External.Custom/Api.Auth.External.Custom.Models/Api.Auth.External.Custom.Models.csproj
+++ b/Api.Auth.External.Custom/Api.Auth.External.Custom.Models/Api.Auth.External.Custom.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Auth.External.Custom/Api.Auth.External.Custom/Dockerfile.Local b/Api.Auth.External.Custom/Api.Auth.External.Custom/Dockerfile.Local
index 4d00259a..d95cf1e7 100644
--- a/Api.Auth.External.Custom/Api.Auth.External.Custom/Dockerfile.Local
+++ b/Api.Auth.External.Custom/Api.Auth.External.Custom/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Auth.External.Custom.dll"]
\ No newline at end of file
diff --git a/Api.Auth.External.Custom/Dockerfile b/Api.Auth.External.Custom/Dockerfile
index 2a07e09b..63fc7b88 100644
--- a/Api.Auth.External.Custom/Dockerfile
+++ b/Api.Auth.External.Custom/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Auth.External.Custom/README.md b/Api.Auth.External.Custom/README.md
index dc8fc4a4..5252ffaf 100644
--- a/Api.Auth.External.Custom/README.md
+++ b/Api.Auth.External.Custom/README.md
@@ -82,6 +82,30 @@ Configured the application with the necessary authentication setup.
}
```
+...and for `Staging` and `Production` environments.
+
+```json
+"App": {
+ "Authentication": {
+ "Jwt": {
+ "Issuer": "nano.staging",
+ "Audience": "nano.staging"
+ }
+ }
+}
+```
+
+```json
+"App": {
+ "Authentication": {
+ "Jwt": {
+ "Issuer": "nano.production",
+ "Audience": "nano.production"
+ }
+ }
+}
+```
+
## Kubernetes
For `Staging` and `Production` environments, a secret must be created to securely store the public and private keys, and optionally the credentials for `RootLogin` if it shoud be
enabled. Below demonstrates how to map the secret containing the JWT keys.
diff --git a/Api.Auth.RootLogin/.github/workflows/build-and-deploy.yml b/Api.Auth.RootLogin/.github/workflows/build-and-deploy.yml
index b33ac0de..8283c158 100644
--- a/Api.Auth.RootLogin/.github/workflows/build-and-deploy.yml
+++ b/Api.Auth.RootLogin/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Auth.RootLogin
IMAGE_NAME: api.auth.rootlogin
SERVICE_NAME: api-auth-rootlogin
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,22 +34,21 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
- AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
+ AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,68 +61,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -165,7 +159,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -173,6 +167,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Auth.RootLogin/.kubernetes/configmap.yaml b/Api.Auth.RootLogin/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Auth.RootLogin/.kubernetes/configmap.yaml
+++ b/Api.Auth.RootLogin/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Auth.RootLogin/.kubernetes/deployment.yaml b/Api.Auth.RootLogin/.kubernetes/deployment.yaml
index aca5889f..6ea6a615 100644
--- a/Api.Auth.RootLogin/.kubernetes/deployment.yaml
+++ b/Api.Auth.RootLogin/.kubernetes/deployment.yaml
@@ -84,6 +84,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Auth.RootLogin/Api.Auth.RootLogin.Models/Api.Auth.RootLogin.Models.csproj b/Api.Auth.RootLogin/Api.Auth.RootLogin.Models/Api.Auth.RootLogin.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Auth.RootLogin/Api.Auth.RootLogin.Models/Api.Auth.RootLogin.Models.csproj
+++ b/Api.Auth.RootLogin/Api.Auth.RootLogin.Models/Api.Auth.RootLogin.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Auth.RootLogin/Api.Auth.RootLogin/Dockerfile.Local b/Api.Auth.RootLogin/Api.Auth.RootLogin/Dockerfile.Local
index d87906a5..97c76dbc 100644
--- a/Api.Auth.RootLogin/Api.Auth.RootLogin/Dockerfile.Local
+++ b/Api.Auth.RootLogin/Api.Auth.RootLogin/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Auth.RootLogin.dll"]
\ No newline at end of file
diff --git a/Api.Auth.RootLogin/Dockerfile b/Api.Auth.RootLogin/Dockerfile
index 3330579b..30705e8f 100644
--- a/Api.Auth.RootLogin/Dockerfile
+++ b/Api.Auth.RootLogin/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Auth.RootLogin/README.md b/Api.Auth.RootLogin/README.md
index a7c64602..b11731fb 100644
--- a/Api.Auth.RootLogin/README.md
+++ b/Api.Auth.RootLogin/README.md
@@ -82,6 +82,30 @@ Configured the application with the necessary authentication setup.
}
```
+...and for `Staging` and `Production` environments.
+
+```json
+"App": {
+ "Authentication": {
+ "Jwt": {
+ "Issuer": "nano.staging",
+ "Audience": "nano.staging"
+ }
+ }
+}
+```
+
+```json
+"App": {
+ "Authentication": {
+ "Jwt": {
+ "Issuer": "nano.production",
+ "Audience": "nano.production"
+ }
+ }
+}
+```
+
## Kubernetes
For `Staging` and `Production` environments, a secret must be created to securely store the public and private keys, and optionally the credentials for `RootLogin` if it shoud be
enabled. Below demonstrates how to map the secret containing the JWT keys.
@@ -114,11 +138,3 @@ env:
```
...and created during the Kubernetes deploy step.
-
-```yaml
-sudo kubectl create secret generic auth-jwt-secret --from-literal=jwt-public-key=$env:AUTH_JWT_PUBLIC_KEY --from-literal=jwt-private-key=$env:AUTH_JWT_PRIVATE_KEY --save-config --dry-run=client -o yaml | sudo kubectl apply -f -;
-if ($LastExitCode -ne 0)
-{
- throw "error";
-};
-```
diff --git a/Api.Authorization/.github/workflows/build-and-deploy.yml b/Api.Authorization/.github/workflows/build-and-deploy.yml
index 27a37e6b..3be9faad 100644
--- a/Api.Authorization/.github/workflows/build-and-deploy.yml
+++ b/Api.Authorization/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Authorization
IMAGE_NAME: api.authorization
SERVICE_NAME: api-authorization
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,22 +34,21 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
- AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
+ AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,68 +61,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -165,7 +159,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -173,6 +167,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Authorization/.kubernetes/configmap.yaml b/Api.Authorization/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Authorization/.kubernetes/configmap.yaml
+++ b/Api.Authorization/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Authorization/.kubernetes/deployment.yaml b/Api.Authorization/.kubernetes/deployment.yaml
index aca5889f..6ea6a615 100644
--- a/Api.Authorization/.kubernetes/deployment.yaml
+++ b/Api.Authorization/.kubernetes/deployment.yaml
@@ -84,6 +84,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Authorization/Api.Authorization.Models/Api.Authorization.Models.csproj b/Api.Authorization/Api.Authorization.Models/Api.Authorization.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Authorization/Api.Authorization.Models/Api.Authorization.Models.csproj
+++ b/Api.Authorization/Api.Authorization.Models/Api.Authorization.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Authorization/Api.Authorization/Dockerfile.Local b/Api.Authorization/Api.Authorization/Dockerfile.Local
index bd2f4fec..a4fd5442 100644
--- a/Api.Authorization/Api.Authorization/Dockerfile.Local
+++ b/Api.Authorization/Api.Authorization/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Authorization.dll"]
\ No newline at end of file
diff --git a/Api.Authorization/Dockerfile b/Api.Authorization/Dockerfile
index 3a70d191..19ff6910 100644
--- a/Api.Authorization/Dockerfile
+++ b/Api.Authorization/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ContentNegotiation/.github/workflows/build-and-deploy.yml b/Api.ContentNegotiation/.github/workflows/build-and-deploy.yml
index 2b200b6d..d64e353f 100644
--- a/Api.ContentNegotiation/.github/workflows/build-and-deploy.yml
+++ b/Api.ContentNegotiation/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ContentNegotiation
IMAGE_NAME: api.contentnegotiation
SERVICE_NAME: api-contentnegotiation
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ContentNegotiation/.kubernetes/configmap.yaml b/Api.ContentNegotiation/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ContentNegotiation/.kubernetes/configmap.yaml
+++ b/Api.ContentNegotiation/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ContentNegotiation/.kubernetes/deployment.yaml b/Api.ContentNegotiation/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ContentNegotiation/.kubernetes/deployment.yaml
+++ b/Api.ContentNegotiation/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ContentNegotiation/Api.ContentNegotiation.Models/Api.ContentNegotiation.Models.csproj b/Api.ContentNegotiation/Api.ContentNegotiation.Models/Api.ContentNegotiation.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ContentNegotiation/Api.ContentNegotiation.Models/Api.ContentNegotiation.Models.csproj
+++ b/Api.ContentNegotiation/Api.ContentNegotiation.Models/Api.ContentNegotiation.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ContentNegotiation/Api.ContentNegotiation/Dockerfile.Local b/Api.ContentNegotiation/Api.ContentNegotiation/Dockerfile.Local
index dc9daf88..f9204f6d 100644
--- a/Api.ContentNegotiation/Api.ContentNegotiation/Dockerfile.Local
+++ b/Api.ContentNegotiation/Api.ContentNegotiation/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ContentNegotiation.dll"]
\ No newline at end of file
diff --git a/Api.ContentNegotiation/Dockerfile b/Api.ContentNegotiation/Dockerfile
index 658250a4..d2576397 100644
--- a/Api.ContentNegotiation/Dockerfile
+++ b/Api.ContentNegotiation/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Cookies/.github/workflows/build-and-deploy.yml b/Api.Cookies/.github/workflows/build-and-deploy.yml
index 3a341c47..0e78026c 100644
--- a/Api.Cookies/.github/workflows/build-and-deploy.yml
+++ b/Api.Cookies/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Cookies
IMAGE_NAME: api.cookies
SERVICE_NAME: api-cookies
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Cookies/.kubernetes/configmap.yaml b/Api.Cookies/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Cookies/.kubernetes/configmap.yaml
+++ b/Api.Cookies/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Cookies/.kubernetes/deployment.yaml b/Api.Cookies/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Cookies/.kubernetes/deployment.yaml
+++ b/Api.Cookies/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Cookies/Api.Cookies.Models/Api.Cookies.Models.csproj b/Api.Cookies/Api.Cookies.Models/Api.Cookies.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Cookies/Api.Cookies.Models/Api.Cookies.Models.csproj
+++ b/Api.Cookies/Api.Cookies.Models/Api.Cookies.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Cookies/Api.Cookies/Dockerfile.Local b/Api.Cookies/Api.Cookies/Dockerfile.Local
index 09cc9dd0..04fd490c 100644
--- a/Api.Cookies/Api.Cookies/Dockerfile.Local
+++ b/Api.Cookies/Api.Cookies/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Cookies.dll"]
\ No newline at end of file
diff --git a/Api.Cookies/Dockerfile b/Api.Cookies/Dockerfile
index 2f4f37d9..7985f6cc 100644
--- a/Api.Cookies/Dockerfile
+++ b/Api.Cookies/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.CustomConfigSection/.github/workflows/build-and-deploy.yml b/Api.CustomConfigSection/.github/workflows/build-and-deploy.yml
index add53801..56f5faa3 100644
--- a/Api.CustomConfigSection/.github/workflows/build-and-deploy.yml
+++ b/Api.CustomConfigSection/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.CustomConfigSection
IMAGE_NAME: api.customconfigsection
SERVICE_NAME: api-customconfigsection
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.CustomConfigSection/.kubernetes/configmap.yaml b/Api.CustomConfigSection/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.CustomConfigSection/.kubernetes/configmap.yaml
+++ b/Api.CustomConfigSection/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.CustomConfigSection/.kubernetes/deployment.yaml b/Api.CustomConfigSection/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.CustomConfigSection/.kubernetes/deployment.yaml
+++ b/Api.CustomConfigSection/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.CustomConfigSection/Api.CustomConfigSection.Models/Api.CustomConfigSection.Models.csproj b/Api.CustomConfigSection/Api.CustomConfigSection.Models/Api.CustomConfigSection.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.CustomConfigSection/Api.CustomConfigSection.Models/Api.CustomConfigSection.Models.csproj
+++ b/Api.CustomConfigSection/Api.CustomConfigSection.Models/Api.CustomConfigSection.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.CustomConfigSection/Api.CustomConfigSection/Dockerfile.Local b/Api.CustomConfigSection/Api.CustomConfigSection/Dockerfile.Local
index 96d8dc2e..5e73c684 100644
--- a/Api.CustomConfigSection/Api.CustomConfigSection/Dockerfile.Local
+++ b/Api.CustomConfigSection/Api.CustomConfigSection/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.CustomConfigSection.dll"]
\ No newline at end of file
diff --git a/Api.CustomConfigSection/Dockerfile b/Api.CustomConfigSection/Dockerfile
index ee947826..8bf39f61 100644
--- a/Api.CustomConfigSection/Dockerfile
+++ b/Api.CustomConfigSection/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.CustomMiddleware/.github/workflows/build-and-deploy.yml b/Api.CustomMiddleware/.github/workflows/build-and-deploy.yml
index b1ae72ca..ee9281bc 100644
--- a/Api.CustomMiddleware/.github/workflows/build-and-deploy.yml
+++ b/Api.CustomMiddleware/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.CustomMiddleware
IMAGE_NAME: api.custommiddleware
SERVICE_NAME: api-custommiddleware
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.CustomMiddleware/.kubernetes/configmap.yaml b/Api.CustomMiddleware/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.CustomMiddleware/.kubernetes/configmap.yaml
+++ b/Api.CustomMiddleware/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.CustomMiddleware/.kubernetes/deployment.yaml b/Api.CustomMiddleware/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.CustomMiddleware/.kubernetes/deployment.yaml
+++ b/Api.CustomMiddleware/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.CustomMiddleware/Api.CustomMiddleware.Models/Api.CustomMiddleware.Models.csproj b/Api.CustomMiddleware/Api.CustomMiddleware.Models/Api.CustomMiddleware.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.CustomMiddleware/Api.CustomMiddleware.Models/Api.CustomMiddleware.Models.csproj
+++ b/Api.CustomMiddleware/Api.CustomMiddleware.Models/Api.CustomMiddleware.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.CustomMiddleware/Api.CustomMiddleware/Dockerfile.Local b/Api.CustomMiddleware/Api.CustomMiddleware/Dockerfile.Local
index e059926f..40ba371d 100644
--- a/Api.CustomMiddleware/Api.CustomMiddleware/Dockerfile.Local
+++ b/Api.CustomMiddleware/Api.CustomMiddleware/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.CustomMiddleware.dll"]
\ No newline at end of file
diff --git a/Api.CustomMiddleware/Dockerfile b/Api.CustomMiddleware/Dockerfile
index a5772da5..102e9115 100644
--- a/Api.CustomMiddleware/Dockerfile
+++ b/Api.CustomMiddleware/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.CustomService/.github/workflows/build-and-deploy.yml b/Api.CustomService/.github/workflows/build-and-deploy.yml
index 4cb38d5a..8f88f093 100644
--- a/Api.CustomService/.github/workflows/build-and-deploy.yml
+++ b/Api.CustomService/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.CustomService
IMAGE_NAME: api.customservice
SERVICE_NAME: api-customservice
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.CustomService/.kubernetes/configmap.yaml b/Api.CustomService/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.CustomService/.kubernetes/configmap.yaml
+++ b/Api.CustomService/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.CustomService/.kubernetes/deployment.yaml b/Api.CustomService/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.CustomService/.kubernetes/deployment.yaml
+++ b/Api.CustomService/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.CustomService/Api.CustomService.Models/Api.CustomService.Models.csproj b/Api.CustomService/Api.CustomService.Models/Api.CustomService.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.CustomService/Api.CustomService.Models/Api.CustomService.Models.csproj
+++ b/Api.CustomService/Api.CustomService.Models/Api.CustomService.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.CustomService/Api.CustomService/Dockerfile.Local b/Api.CustomService/Api.CustomService/Dockerfile.Local
index 83ac0c36..21f64860 100644
--- a/Api.CustomService/Api.CustomService/Dockerfile.Local
+++ b/Api.CustomService/Api.CustomService/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.CustomService.dll"]
\ No newline at end of file
diff --git a/Api.CustomService/Dockerfile b/Api.CustomService/Dockerfile
index 8679c6c7..4265f374 100644
--- a/Api.CustomService/Dockerfile
+++ b/Api.CustomService/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.Audit/.docker/docker-compose.yml b/Api.Data.Audit/.docker/docker-compose.yml
index ee96146f..0b053f4a 100644
--- a/Api.Data.Audit/.docker/docker-compose.yml
+++ b/Api.Data.Audit/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Audit/.github/workflows/build-and-deploy.yml b/Api.Data.Audit/.github/workflows/build-and-deploy.yml
index e8e13f4a..d5c6262c 100644
--- a/Api.Data.Audit/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Audit/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Audit
IMAGE_NAME: api.data.audit
SERVICE_NAME: api-data-audit
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Audit/.kubernetes/auth-sql-secret.yaml b/Api.Data.Audit/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Audit/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Audit/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Audit/.kubernetes/configmap.yaml b/Api.Data.Audit/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Audit/.kubernetes/configmap.yaml
+++ b/Api.Data.Audit/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Audit/.kubernetes/deployment.yaml b/Api.Data.Audit/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.Audit/.kubernetes/deployment.yaml
+++ b/Api.Data.Audit/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Audit/Api.Data.Audit.Models/Api.Data.Audit.Models.csproj b/Api.Data.Audit/Api.Data.Audit.Models/Api.Data.Audit.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Audit/Api.Data.Audit.Models/Api.Data.Audit.Models.csproj
+++ b/Api.Data.Audit/Api.Data.Audit.Models/Api.Data.Audit.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Audit/Api.Data.Audit/Dockerfile.Local b/Api.Data.Audit/Api.Data.Audit/Dockerfile.Local
index 02405ae6..4660beaf 100644
--- a/Api.Data.Audit/Api.Data.Audit/Dockerfile.Local
+++ b/Api.Data.Audit/Api.Data.Audit/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Audit.dll"]
\ No newline at end of file
diff --git a/Api.Data.Audit/Api.Data.Audit/appsettings.Development.json b/Api.Data.Audit/Api.Data.Audit/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.Audit/Api.Data.Audit/appsettings.Development.json
+++ b/Api.Data.Audit/Api.Data.Audit/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Audit/Dockerfile b/Api.Data.Audit/Dockerfile
index d8e60daa..a58c06ab 100644
--- a/Api.Data.Audit/Dockerfile
+++ b/Api.Data.Audit/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.EntityEvents/.docker/docker-compose.yml b/Api.Data.EntityEvents/.docker/docker-compose.yml
index c7513f0a..de7e7113 100644
--- a/Api.Data.EntityEvents/.docker/docker-compose.yml
+++ b/Api.Data.EntityEvents/.docker/docker-compose.yml
@@ -36,8 +36,8 @@ services:
networks:
- network
environment:
- MYSQL_ROOT_PASSWORD: myPassword_123
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
diff --git a/Api.Data.EntityEvents/.github/workflows/build-and-deploy.yml b/Api.Data.EntityEvents/.github/workflows/build-and-deploy.yml
index ab07e819..7ebe9759 100644
--- a/Api.Data.EntityEvents/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.EntityEvents/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.EntityEvents
IMAGE_NAME: api.data.entityevents
SERVICE_NAME: api-data-entityevents
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.EntityEvents/.kubernetes/auth-sql-secret.yaml b/Api.Data.EntityEvents/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.EntityEvents/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.EntityEvents/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.EntityEvents/.kubernetes/configmap.yaml b/Api.Data.EntityEvents/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.EntityEvents/.kubernetes/configmap.yaml
+++ b/Api.Data.EntityEvents/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.EntityEvents/.kubernetes/deployment.yaml b/Api.Data.EntityEvents/.kubernetes/deployment.yaml
index ddbdae40..5181e537 100644
--- a/Api.Data.EntityEvents/.kubernetes/deployment.yaml
+++ b/Api.Data.EntityEvents/.kubernetes/deployment.yaml
@@ -48,7 +48,6 @@ spec:
secretKeyRef:
name: rabbitmq-auth
key: username
- envFrom:
- name: Eventing__Credentials__Secret
valueFrom:
secretKeyRef:
@@ -90,6 +89,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.EntityEvents/Api.Data.EntityEvents.Models/Api.Data.EntityEvents.Models.csproj b/Api.Data.EntityEvents/Api.Data.EntityEvents.Models/Api.Data.EntityEvents.Models.csproj
index c58bf942..1a71ff2f 100644
--- a/Api.Data.EntityEvents/Api.Data.EntityEvents.Models/Api.Data.EntityEvents.Models.csproj
+++ b/Api.Data.EntityEvents/Api.Data.EntityEvents.Models/Api.Data.EntityEvents.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber.Models/Api.Data.EntityEvents.Subscriber.Models.csproj b/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber.Models/Api.Data.EntityEvents.Subscriber.Models.csproj
index c58bf942..1a71ff2f 100644
--- a/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber.Models/Api.Data.EntityEvents.Subscriber.Models.csproj
+++ b/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber.Models/Api.Data.EntityEvents.Subscriber.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/Dockerfile.Local b/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/Dockerfile.Local
index 6d48bd26..7b2731b0 100644
--- a/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/Dockerfile.Local
+++ b/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.EntityEvents.Subscriber.dll"]
\ No newline at end of file
diff --git a/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/appsettings.Development.json b/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/appsettings.Development.json
index 4de4ef5b..4cd2baad 100644
--- a/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/appsettings.Development.json
+++ b/Api.Data.EntityEvents/Api.Data.EntityEvents.Subscriber/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb2;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb2;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.EntityEvents/Api.Data.EntityEvents/Dockerfile.Local b/Api.Data.EntityEvents/Api.Data.EntityEvents/Dockerfile.Local
index b78f25ae..019c7fef 100644
--- a/Api.Data.EntityEvents/Api.Data.EntityEvents/Dockerfile.Local
+++ b/Api.Data.EntityEvents/Api.Data.EntityEvents/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.EntityEvents.dll"]
\ No newline at end of file
diff --git a/Api.Data.EntityEvents/Api.Data.EntityEvents/appsettings.Development.json b/Api.Data.EntityEvents/Api.Data.EntityEvents/appsettings.Development.json
index 74c8964f..3ccddc18 100644
--- a/Api.Data.EntityEvents/Api.Data.EntityEvents/appsettings.Development.json
+++ b/Api.Data.EntityEvents/Api.Data.EntityEvents/appsettings.Development.json
@@ -1,7 +1,7 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
},
"Eventing": {
"Credentials": {
diff --git a/Api.Data.EntityEvents/Dockerfile b/Api.Data.EntityEvents/Dockerfile
index dca7eca5..5d8feeb5 100644
--- a/Api.Data.EntityEvents/Dockerfile
+++ b/Api.Data.EntityEvents/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.Identity.Auth.ApiKey/.docker/docker-compose.yml b/Api.Data.Identity.Auth.ApiKey/.docker/docker-compose.yml
index d7305c76..e8a95380 100644
--- a/Api.Data.Identity.Auth.ApiKey/.docker/docker-compose.yml
+++ b/Api.Data.Identity.Auth.ApiKey/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Identity.Auth.ApiKey/.github/workflows/build-and-deploy.yml b/Api.Data.Identity.Auth.ApiKey/.github/workflows/build-and-deploy.yml
index e43c9804..66e9d4cd 100644
--- a/Api.Data.Identity.Auth.ApiKey/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Identity.Auth.ApiKey/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Identity.Auth.ApiKey
IMAGE_NAME: api.data.identity.auth.apikey
SERVICE_NAME: api-data-identity.auth.apikey
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,25 +38,24 @@ env:
KUBERNETES_CPU_SCALING: 180
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
- AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
- AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
- AUTH_API_KEY_SECRET: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_API_KEY_SECRET || secrets.STAGING_AUTH_API_KEY_SECRET }}
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
+ AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
+ AUTH_API_KEY_SECRET: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_API_KEY_SECRET || secrets.STAGING_AUTH_API_KEY_SECRET }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -69,86 +68,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -177,7 +178,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -229,7 +230,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -237,6 +238,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Identity.Auth.ApiKey/.kubernetes/auth-sql-secret.yaml b/Api.Data.Identity.Auth.ApiKey/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Identity.Auth.ApiKey/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Identity.Auth.ApiKey/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Identity.Auth.ApiKey/.kubernetes/configmap.yaml b/Api.Data.Identity.Auth.ApiKey/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Identity.Auth.ApiKey/.kubernetes/configmap.yaml
+++ b/Api.Data.Identity.Auth.ApiKey/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Identity.Auth.ApiKey/.kubernetes/deployment.yaml b/Api.Data.Identity.Auth.ApiKey/.kubernetes/deployment.yaml
index c8c3659c..3824a48e 100644
--- a/Api.Data.Identity.Auth.ApiKey/.kubernetes/deployment.yaml
+++ b/Api.Data.Identity.Auth.ApiKey/.kubernetes/deployment.yaml
@@ -94,6 +94,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey.Models/Api.Data.Identity.Auth.ApiKey.Models.csproj b/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey.Models/Api.Data.Identity.Auth.ApiKey.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey.Models/Api.Data.Identity.Auth.ApiKey.Models.csproj
+++ b/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey.Models/Api.Data.Identity.Auth.ApiKey.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/Dockerfile.Local b/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/Dockerfile.Local
index bab003df..4b93dba9 100644
--- a/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/Dockerfile.Local
+++ b/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Identity.Auth.ApiKey.dll"]
\ No newline at end of file
diff --git a/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/appsettings.Development.json b/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/appsettings.Development.json
index 223c8a7b..12cbb219 100644
--- a/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/appsettings.Development.json
+++ b/Api.Data.Identity.Auth.ApiKey/Api.Data.Identity.Auth.ApiKey/appsettings.Development.json
@@ -13,6 +13,6 @@
},
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Identity.Auth.ApiKey/Dockerfile b/Api.Data.Identity.Auth.ApiKey/Dockerfile
index 30ab00dc..94f9f717 100644
--- a/Api.Data.Identity.Auth.ApiKey/Dockerfile
+++ b/Api.Data.Identity.Auth.ApiKey/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.Identity.Auth.ApiKey/README.md b/Api.Data.Identity.Auth.ApiKey/README.md
index 45050da2..5f34e140 100644
--- a/Api.Data.Identity.Auth.ApiKey/README.md
+++ b/Api.Data.Identity.Auth.ApiKey/README.md
@@ -48,17 +48,17 @@ Additionally, the identity controller is also avaialble, and the actions can be
Configured the application with the necessary authentication setup, in addition to the existing identity and jwt configuration.
```json
-"App": {
- "Data": {
- "Identity": {
- "ApiKey": {
- "Secret": "secret"
- }
+"Data": {
+ "Identity": {
+ "ApiKey": {
+ "Secret": "secret"
}
}
}
```
+Additionally, JWT authentication has been configured to enable the application to generate JWT tokens based on an API key.
+
## Kubernetes
For `Staging` and `Production` environments, a secret must be created to securely store the apikey secret. Below demonstrates how to map the secret containing the API key secret.
diff --git a/Api.Data.Identity.Auth.External.Custom/.docker/docker-compose.yml b/Api.Data.Identity.Auth.External.Custom/.docker/docker-compose.yml
index 921f1be5..77810132 100644
--- a/Api.Data.Identity.Auth.External.Custom/.docker/docker-compose.yml
+++ b/Api.Data.Identity.Auth.External.Custom/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Identity.Auth.External.Custom/.github/workflows/build-and-deploy.yml b/Api.Data.Identity.Auth.External.Custom/.github/workflows/build-and-deploy.yml
index 49b0d6db..31fc303f 100644
--- a/Api.Data.Identity.Auth.External.Custom/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Identity.Auth.External.Custom/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Identity.Auth.External.Custom
IMAGE_NAME: api.data.identity.auth.external.custom
SERVICE_NAME: api-data-identity.auth.external.custom
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,24 +38,23 @@ env:
KUBERNETES_CPU_SCALING: 180
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
- AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
- AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
+ AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -68,86 +67,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -176,7 +177,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -221,7 +222,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -229,6 +230,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Identity.Auth.External.Custom/.kubernetes/auth-sql-secret.yaml b/Api.Data.Identity.Auth.External.Custom/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Identity.Auth.External.Custom/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Identity.Auth.External.Custom/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Identity.Auth.External.Custom/.kubernetes/configmap.yaml b/Api.Data.Identity.Auth.External.Custom/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Identity.Auth.External.Custom/.kubernetes/configmap.yaml
+++ b/Api.Data.Identity.Auth.External.Custom/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Identity.Auth.External.Custom/.kubernetes/deployment.yaml b/Api.Data.Identity.Auth.External.Custom/.kubernetes/deployment.yaml
index f615e1a7..7b7d2e61 100644
--- a/Api.Data.Identity.Auth.External.Custom/.kubernetes/deployment.yaml
+++ b/Api.Data.Identity.Auth.External.Custom/.kubernetes/deployment.yaml
@@ -89,6 +89,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom.Models/Api.Data.Identity.Auth.External.Custom.Models.csproj b/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom.Models/Api.Data.Identity.Auth.External.Custom.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom.Models/Api.Data.Identity.Auth.External.Custom.Models.csproj
+++ b/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom.Models/Api.Data.Identity.Auth.External.Custom.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/Dockerfile.Local b/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/Dockerfile.Local
index a00c6450..8a572c27 100644
--- a/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/Dockerfile.Local
+++ b/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Identity.Auth.External.Custom.dll"]
\ No newline at end of file
diff --git a/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/appsettings.Development.json b/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/appsettings.Development.json
index 223c8a7b..12cbb219 100644
--- a/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/appsettings.Development.json
+++ b/Api.Data.Identity.Auth.External.Custom/Api.Data.Identity.Auth.External.Custom/appsettings.Development.json
@@ -13,6 +13,6 @@
},
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Identity.Auth.External.Custom/Dockerfile b/Api.Data.Identity.Auth.External.Custom/Dockerfile
index 5a2e6a5e..38d1a8bd 100644
--- a/Api.Data.Identity.Auth.External.Custom/Dockerfile
+++ b/Api.Data.Identity.Auth.External.Custom/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.Identity.Auth.External.Custom/README.md b/Api.Data.Identity.Auth.External.Custom/README.md
index f9e7730c..43ebf51f 100644
--- a/Api.Data.Identity.Auth.External.Custom/README.md
+++ b/Api.Data.Identity.Auth.External.Custom/README.md
@@ -14,7 +14,6 @@ Nano is referenced directly from source (not via NuGet packages) and is expected
## Table of Contents
* [Summary](#summary)
-* [Configuration](#configuration)
## Summary
This application builds on **[Api.Data.Identity.Auth.Jwt](https://github.com/Nano-Core/Nano.Lessons/tree/master/Api.Data.Identity.Auth.Jwt)**.
@@ -51,36 +50,3 @@ The following new endpoints related to the custom authentication provider from t
> 📖 Learn more about **[Nano Authentication](https://github.com/Nano-Core/Nano.Library/tree/master/Nano.App.Api/README.md#authentication)**.
-## Configuration
-Configured the application with the necessary authentication setup, in addition to the identity configuration.
-
-```json
-"App": {
- "Authentication": {
- "Jwt": {
- "Issuer": null,
- "Audience": null,
- "PublicKey": null,
- "PrivateKey": null,
- "Expiration": "01:00:00",
- "RefreshExpiration": "72:00:00"
- }
- }
-}
-```
-
-...and for `appesettings.Developmnet.json`.
-
-```json
-"App": {
- "Authentication": {
- "Jwt": {
- "Issuer": "Development.nano",
- "Audience": "Development.nano",
- "PublicKey": "MIIBCgKCAQEAv7iVNUS5w...",
- "PrivateKey": "MIIEowIBAAKCAQEAv7iV...",
- "Expiration": "24:00:00"
- }
- }
-}
-```
diff --git a/Api.Data.Identity.Auth.Jwt/.docker/docker-compose.yml b/Api.Data.Identity.Auth.Jwt/.docker/docker-compose.yml
index 69136e45..599c4f0c 100644
--- a/Api.Data.Identity.Auth.Jwt/.docker/docker-compose.yml
+++ b/Api.Data.Identity.Auth.Jwt/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Identity.Auth.Jwt/.github/workflows/build-and-deploy.yml b/Api.Data.Identity.Auth.Jwt/.github/workflows/build-and-deploy.yml
index 7141f0f2..0975693f 100644
--- a/Api.Data.Identity.Auth.Jwt/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Identity.Auth.Jwt/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Identity.Auth.Jwt
IMAGE_NAME: api.data.identity.auth.jwt
SERVICE_NAME: api-data-identity.auth.jwt
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,24 +38,23 @@ env:
KUBERNETES_CPU_SCALING: 180
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
- AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
- AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ AUTH_JWT_PUBLIC_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PUBLIC_KEY || secrets.STAGING_AUTH_JWT_PUBLIC_KEY }}
+ AUTH_JWT_PRIVATE_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AUTH_JWT_PRIVATE_KEY || secrets.STAGING_AUTH_JWT_PRIVATE_KEY }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -68,86 +67,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -176,7 +177,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -221,7 +222,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -229,6 +230,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Identity.Auth.Jwt/.kubernetes/auth-sql-secret.yaml b/Api.Data.Identity.Auth.Jwt/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Identity.Auth.Jwt/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Identity.Auth.Jwt/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Identity.Auth.Jwt/.kubernetes/configmap.yaml b/Api.Data.Identity.Auth.Jwt/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Identity.Auth.Jwt/.kubernetes/configmap.yaml
+++ b/Api.Data.Identity.Auth.Jwt/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Identity.Auth.Jwt/.kubernetes/deployment.yaml b/Api.Data.Identity.Auth.Jwt/.kubernetes/deployment.yaml
index f615e1a7..7b7d2e61 100644
--- a/Api.Data.Identity.Auth.Jwt/.kubernetes/deployment.yaml
+++ b/Api.Data.Identity.Auth.Jwt/.kubernetes/deployment.yaml
@@ -89,6 +89,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt.Models/Api.Data.Identity.Auth.Jwt.Models.csproj b/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt.Models/Api.Data.Identity.Auth.Jwt.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt.Models/Api.Data.Identity.Auth.Jwt.Models.csproj
+++ b/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt.Models/Api.Data.Identity.Auth.Jwt.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/Dockerfile.Local b/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/Dockerfile.Local
index 678ca81b..ee5ad4a0 100644
--- a/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/Dockerfile.Local
+++ b/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Identity.Auth.Jwt.dll"]
\ No newline at end of file
diff --git a/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/appsettings.Development.json b/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/appsettings.Development.json
index 223c8a7b..12cbb219 100644
--- a/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/appsettings.Development.json
+++ b/Api.Data.Identity.Auth.Jwt/Api.Data.Identity.Auth.Jwt/appsettings.Development.json
@@ -13,6 +13,6 @@
},
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Identity.Auth.Jwt/Dockerfile b/Api.Data.Identity.Auth.Jwt/Dockerfile
index d166ebde..9c666c21 100644
--- a/Api.Data.Identity.Auth.Jwt/Dockerfile
+++ b/Api.Data.Identity.Auth.Jwt/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.Identity.Auth.Jwt/README.md b/Api.Data.Identity.Auth.Jwt/README.md
index bfbaf354..a8c3c174 100644
--- a/Api.Data.Identity.Auth.Jwt/README.md
+++ b/Api.Data.Identity.Auth.Jwt/README.md
@@ -75,8 +75,32 @@ Configured the application with the necessary authentication setup, in addition
}
```
+...and for `Staging` and `Production` environments.
+
+```json
+"App": {
+ "Authentication": {
+ "Jwt": {
+ "Issuer": "nano.staging",
+ "Audience": "nano.staging"
+ }
+ }
+}
+```
+
+```json
+"App": {
+ "Authentication": {
+ "Jwt": {
+ "Issuer": "nano.production",
+ "Audience": "nano.production"
+ }
+ }
+}
+```
+
## Kubernetes
-For `Staging` and `Production` environments, a secret must be created to securely store the public and private keys, and optionally the credentials for `RootLogin` if it shoud be
+For `Staging` and `Production` environments, a `auth-jwt-secret.yaml` is also created to securely store the public and private keys, and optionally the credentials for `RootLogin` if it shoud be
enabled. Below demonstrates how to map the secret containing the JWT keys.
```yaml
@@ -98,7 +122,7 @@ spec:
```
## GitHub Action
-The secrets defined in GitHub must also be mapped for the `Staging` and `Production` environments in the `build-and-deploy.yml` workflow, as shown below.
+The secrets defined in GitHub must also be inbcluded in environmental variables for `Staging` and `Production` environments in the `build-and-deploy.yml` workflow, as shown below.
```yaml
env:
@@ -107,12 +131,3 @@ env:
```
...and created during the Kubernetes deploy step.
-
-```yaml
-sudo kubectl create secret generic auth-jwt-secret --from-literal=jwt-public-key=$env:AUTH_JWT_PUBLIC_KEY --from-literal=jwt-private-key=$env:AUTH_JWT_PRIVATE_KEY --save-config --dry-run=client -o yaml | sudo kubectl apply -f -;
-if ($LastExitCode -ne 0)
-{
- throw "error";
-};
-```
-
diff --git a/Api.Data.Identity/.docker/docker-compose.yml b/Api.Data.Identity/.docker/docker-compose.yml
index d4a7e47a..6b6b16db 100644
--- a/Api.Data.Identity/.docker/docker-compose.yml
+++ b/Api.Data.Identity/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Identity/.github/workflows/build-and-deploy.yml b/Api.Data.Identity/.github/workflows/build-and-deploy.yml
index ec82c6b7..2ab2015a 100644
--- a/Api.Data.Identity/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Identity/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Identity
IMAGE_NAME: api.data.identity
SERVICE_NAME: api-data-identity
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Identity/.kubernetes/auth-sql-secret.yaml b/Api.Data.Identity/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Identity/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Identity/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Identity/.kubernetes/configmap.yaml b/Api.Data.Identity/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Identity/.kubernetes/configmap.yaml
+++ b/Api.Data.Identity/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Identity/.kubernetes/deployment.yaml b/Api.Data.Identity/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.Identity/.kubernetes/deployment.yaml
+++ b/Api.Data.Identity/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Identity/Api.Data.Identity.Models/Api.Data.Identity.Models.csproj b/Api.Data.Identity/Api.Data.Identity.Models/Api.Data.Identity.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Identity/Api.Data.Identity.Models/Api.Data.Identity.Models.csproj
+++ b/Api.Data.Identity/Api.Data.Identity.Models/Api.Data.Identity.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Identity/Api.Data.Identity/Dockerfile.Local b/Api.Data.Identity/Api.Data.Identity/Dockerfile.Local
index a05f0920..44a50c05 100644
--- a/Api.Data.Identity/Api.Data.Identity/Dockerfile.Local
+++ b/Api.Data.Identity/Api.Data.Identity/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Identity.dll"]
\ No newline at end of file
diff --git a/Api.Data.Identity/Api.Data.Identity/appsettings.Development.json b/Api.Data.Identity/Api.Data.Identity/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.Identity/Api.Data.Identity/appsettings.Development.json
+++ b/Api.Data.Identity/Api.Data.Identity/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Identity/Dockerfile b/Api.Data.Identity/Dockerfile
index 0e6712aa..bdbd7948 100644
--- a/Api.Data.Identity/Dockerfile
+++ b/Api.Data.Identity/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.InMemory/.github/workflows/build-and-deploy.yml b/Api.Data.InMemory/.github/workflows/build-and-deploy.yml
index 50a2894a..4b960581 100644
--- a/Api.Data.InMemory/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.InMemory/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.InMemory
IMAGE_NAME: api.data.inmemory
SERVICE_NAME: api-data-inmemory
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.InMemory/.kubernetes/configmap.yaml b/Api.Data.InMemory/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.InMemory/.kubernetes/configmap.yaml
+++ b/Api.Data.InMemory/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.InMemory/.kubernetes/deployment.yaml b/Api.Data.InMemory/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Data.InMemory/.kubernetes/deployment.yaml
+++ b/Api.Data.InMemory/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.InMemory/Api.Data.InMemory.Models/Api.Data.InMemory.Models.csproj b/Api.Data.InMemory/Api.Data.InMemory.Models/Api.Data.InMemory.Models.csproj
index f949c7de..c706da29 100644
--- a/Api.Data.InMemory/Api.Data.InMemory.Models/Api.Data.InMemory.Models.csproj
+++ b/Api.Data.InMemory/Api.Data.InMemory.Models/Api.Data.InMemory.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.InMemory/Api.Data.InMemory/Dockerfile.Local b/Api.Data.InMemory/Api.Data.InMemory/Dockerfile.Local
index a61be1c9..e4500893 100644
--- a/Api.Data.InMemory/Api.Data.InMemory/Dockerfile.Local
+++ b/Api.Data.InMemory/Api.Data.InMemory/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.InMemory.dll"]
\ No newline at end of file
diff --git a/Api.Data.InMemory/Dockerfile b/Api.Data.InMemory/Dockerfile
index ff662879..d56f83d7 100644
--- a/Api.Data.InMemory/Dockerfile
+++ b/Api.Data.InMemory/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.InMemory/README.md b/Api.Data.InMemory/README.md
index bb283b02..2bdd8a89 100644
--- a/Api.Data.InMemory/README.md
+++ b/Api.Data.InMemory/README.md
@@ -68,7 +68,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": "nanoDb",
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
diff --git a/Api.Data.LazyLoading/.docker/docker-compose.yml b/Api.Data.LazyLoading/.docker/docker-compose.yml
index b31fee18..986f0034 100644
--- a/Api.Data.LazyLoading/.docker/docker-compose.yml
+++ b/Api.Data.LazyLoading/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.LazyLoading/.github/workflows/build-and-deploy.yml b/Api.Data.LazyLoading/.github/workflows/build-and-deploy.yml
index 2d8de195..93b4c88f 100644
--- a/Api.Data.LazyLoading/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.LazyLoading/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.LazyLoading
IMAGE_NAME: api.data.lazyloading
SERVICE_NAME: api-data-lazyloading
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.LazyLoading/.kubernetes/auth-sql-secret.yaml b/Api.Data.LazyLoading/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.LazyLoading/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.LazyLoading/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.LazyLoading/.kubernetes/configmap.yaml b/Api.Data.LazyLoading/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.LazyLoading/.kubernetes/configmap.yaml
+++ b/Api.Data.LazyLoading/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.LazyLoading/.kubernetes/deployment.yaml b/Api.Data.LazyLoading/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.LazyLoading/.kubernetes/deployment.yaml
+++ b/Api.Data.LazyLoading/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.LazyLoading/Api.Data.LazyLoading.Models/Api.Data.LazyLoading.Models.csproj b/Api.Data.LazyLoading/Api.Data.LazyLoading.Models/Api.Data.LazyLoading.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.LazyLoading/Api.Data.LazyLoading.Models/Api.Data.LazyLoading.Models.csproj
+++ b/Api.Data.LazyLoading/Api.Data.LazyLoading.Models/Api.Data.LazyLoading.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.LazyLoading/Api.Data.LazyLoading/Dockerfile.Local b/Api.Data.LazyLoading/Api.Data.LazyLoading/Dockerfile.Local
index ad93161d..4aeaeeb0 100644
--- a/Api.Data.LazyLoading/Api.Data.LazyLoading/Dockerfile.Local
+++ b/Api.Data.LazyLoading/Api.Data.LazyLoading/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.LazyLoading.dll"]
\ No newline at end of file
diff --git a/Api.Data.LazyLoading/Api.Data.LazyLoading/appsettings.Development.json b/Api.Data.LazyLoading/Api.Data.LazyLoading/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.LazyLoading/Api.Data.LazyLoading/appsettings.Development.json
+++ b/Api.Data.LazyLoading/Api.Data.LazyLoading/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.LazyLoading/Dockerfile b/Api.Data.LazyLoading/Dockerfile
index 14732284..42bbc82f 100644
--- a/Api.Data.LazyLoading/Dockerfile
+++ b/Api.Data.LazyLoading/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql.Collation/.docker/docker-compose.yml b/Api.Data.MySql.Collation/.docker/docker-compose.yml
index edbf3b37..6b453c40 100644
--- a/Api.Data.MySql.Collation/.docker/docker-compose.yml
+++ b/Api.Data.MySql.Collation/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.MySql.Collation/.github/workflows/build-and-deploy.yml b/Api.Data.MySql.Collation/.github/workflows/build-and-deploy.yml
index 530f1d65..32d175e6 100644
--- a/Api.Data.MySql.Collation/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.MySql.Collation/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.MySql.Collation
IMAGE_NAME: api.data.mysql.collation
SERVICE_NAME: api-data-mysql-collation
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,20 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +62,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +172,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +210,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +218,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.MySql.Collation/.kubernetes/auth-sql-secret.yaml b/Api.Data.MySql.Collation/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.MySql.Collation/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.MySql.Collation/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.MySql.Collation/.kubernetes/configmap.yaml b/Api.Data.MySql.Collation/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.MySql.Collation/.kubernetes/configmap.yaml
+++ b/Api.Data.MySql.Collation/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.MySql.Collation/.kubernetes/deployment.yaml b/Api.Data.MySql.Collation/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.MySql.Collation/.kubernetes/deployment.yaml
+++ b/Api.Data.MySql.Collation/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.MySql.Collation/Api.Data.MySql.Collation.Models/Api.Data.MySql.Collation.Models.csproj b/Api.Data.MySql.Collation/Api.Data.MySql.Collation.Models/Api.Data.MySql.Collation.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.MySql.Collation/Api.Data.MySql.Collation.Models/Api.Data.MySql.Collation.Models.csproj
+++ b/Api.Data.MySql.Collation/Api.Data.MySql.Collation.Models/Api.Data.MySql.Collation.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.MySql.Collation/Api.Data.MySql.Collation/Dockerfile.Local b/Api.Data.MySql.Collation/Api.Data.MySql.Collation/Dockerfile.Local
index f2716c69..bb8d99b2 100644
--- a/Api.Data.MySql.Collation/Api.Data.MySql.Collation/Dockerfile.Local
+++ b/Api.Data.MySql.Collation/Api.Data.MySql.Collation/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.MySql.Collation.dll"]
\ No newline at end of file
diff --git a/Api.Data.MySql.Collation/Api.Data.MySql.Collation/appsettings.Development.json b/Api.Data.MySql.Collation/Api.Data.MySql.Collation/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.MySql.Collation/Api.Data.MySql.Collation/appsettings.Development.json
+++ b/Api.Data.MySql.Collation/Api.Data.MySql.Collation/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.MySql.Collation/Dockerfile b/Api.Data.MySql.Collation/Dockerfile
index 0d24bca4..7a43e461 100644
--- a/Api.Data.MySql.Collation/Dockerfile
+++ b/Api.Data.MySql.Collation/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql.Mappings/.docker/docker-compose.yml b/Api.Data.MySql.Mappings/.docker/docker-compose.yml
index 7fe5c2e8..dfecb5b3 100644
--- a/Api.Data.MySql.Mappings/.docker/docker-compose.yml
+++ b/Api.Data.MySql.Mappings/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.MySql.Mappings/.github/workflows/build-and-deploy.yml b/Api.Data.MySql.Mappings/.github/workflows/build-and-deploy.yml
index 4e0460d8..eb341f86 100644
--- a/Api.Data.MySql.Mappings/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.MySql.Mappings/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.MySql.Mappings
IMAGE_NAME: api.data.mysql.mappings
SERVICE_NAME: api-data-mysql-mappings
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.MySql.Mappings/.kubernetes/auth-sql-secret.yaml b/Api.Data.MySql.Mappings/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.MySql.Mappings/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.MySql.Mappings/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.MySql.Mappings/.kubernetes/configmap.yaml b/Api.Data.MySql.Mappings/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.MySql.Mappings/.kubernetes/configmap.yaml
+++ b/Api.Data.MySql.Mappings/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.MySql.Mappings/.kubernetes/deployment.yaml b/Api.Data.MySql.Mappings/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.MySql.Mappings/.kubernetes/deployment.yaml
+++ b/Api.Data.MySql.Mappings/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings.Models/Api.Data.MySql.Mappings.Models.csproj b/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings.Models/Api.Data.MySql.Mappings.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings.Models/Api.Data.MySql.Mappings.Models.csproj
+++ b/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings.Models/Api.Data.MySql.Mappings.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/Dockerfile.Local b/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/Dockerfile.Local
index 88ec81d2..7532a55f 100644
--- a/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/Dockerfile.Local
+++ b/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.MySql.Mappings.dll"]
\ No newline at end of file
diff --git a/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/appsettings.Development.json b/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/appsettings.Development.json
+++ b/Api.Data.MySql.Mappings/Api.Data.MySql.Mappings/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.MySql.Mappings/Dockerfile b/Api.Data.MySql.Mappings/Dockerfile
index bd6047d9..c10505dc 100644
--- a/Api.Data.MySql.Mappings/Dockerfile
+++ b/Api.Data.MySql.Mappings/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql.Spatial/.docker/docker-compose.yml b/Api.Data.MySql.Spatial/.docker/docker-compose.yml
index 309848ae..7c9e8d48 100644
--- a/Api.Data.MySql.Spatial/.docker/docker-compose.yml
+++ b/Api.Data.MySql.Spatial/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.MySql.Spatial/.github/workflows/build-and-deploy.yml b/Api.Data.MySql.Spatial/.github/workflows/build-and-deploy.yml
index 956aec17..5dc3a3d4 100644
--- a/Api.Data.MySql.Spatial/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.MySql.Spatial/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.MySql.Spatial
IMAGE_NAME: api.data.mysql.spatial
SERVICE_NAME: api-data-mysql-spatial
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.MySql.Spatial/.kubernetes/auth-sql-secret.yaml b/Api.Data.MySql.Spatial/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.MySql.Spatial/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.MySql.Spatial/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.MySql.Spatial/.kubernetes/configmap.yaml b/Api.Data.MySql.Spatial/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.MySql.Spatial/.kubernetes/configmap.yaml
+++ b/Api.Data.MySql.Spatial/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.MySql.Spatial/.kubernetes/deployment.yaml b/Api.Data.MySql.Spatial/.kubernetes/deployment.yaml
index 7e8688ef..d910429c 100644
--- a/Api.Data.MySql.Spatial/.kubernetes/deployment.yaml
+++ b/Api.Data.MySql.Spatial/.kubernetes/deployment.yaml
@@ -79,6 +79,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial.Models/Api.Data.MySql.Spatial.Models.csproj b/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial.Models/Api.Data.MySql.Spatial.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial.Models/Api.Data.MySql.Spatial.Models.csproj
+++ b/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial.Models/Api.Data.MySql.Spatial.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/Dockerfile.Local b/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/Dockerfile.Local
index 33203aa6..414bb67a 100644
--- a/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/Dockerfile.Local
+++ b/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.MySql.Spatial.dll"]
\ No newline at end of file
diff --git a/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/appsettings.Development.json b/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/appsettings.Development.json
+++ b/Api.Data.MySql.Spatial/Api.Data.MySql.Spatial/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.MySql.Spatial/Dockerfile b/Api.Data.MySql.Spatial/Dockerfile
index dce34833..2579789c 100644
--- a/Api.Data.MySql.Spatial/Dockerfile
+++ b/Api.Data.MySql.Spatial/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql.StoredProcedures/.docker/docker-compose.yml b/Api.Data.MySql.StoredProcedures/.docker/docker-compose.yml
index 5f01dfb6..58e90a83 100644
--- a/Api.Data.MySql.StoredProcedures/.docker/docker-compose.yml
+++ b/Api.Data.MySql.StoredProcedures/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.MySql.StoredProcedures/.github/workflows/build-and-deploy.yml b/Api.Data.MySql.StoredProcedures/.github/workflows/build-and-deploy.yml
index d7056b63..32bb90c6 100644
--- a/Api.Data.MySql.StoredProcedures/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.MySql.StoredProcedures/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.MySql.StoredProcedures
IMAGE_NAME: api.data.mysql.storedprocedures
SERVICE_NAME: api-data-mysql-storedprocedures
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.MySql.StoredProcedures/.kubernetes/auth-sql-secret.yaml b/Api.Data.MySql.StoredProcedures/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.MySql.StoredProcedures/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.MySql.StoredProcedures/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.MySql.StoredProcedures/.kubernetes/configmap.yaml b/Api.Data.MySql.StoredProcedures/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.MySql.StoredProcedures/.kubernetes/configmap.yaml
+++ b/Api.Data.MySql.StoredProcedures/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.MySql.StoredProcedures/.kubernetes/deployment.yaml b/Api.Data.MySql.StoredProcedures/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.MySql.StoredProcedures/.kubernetes/deployment.yaml
+++ b/Api.Data.MySql.StoredProcedures/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures.Models/Api.Data.MySql.StoredProcedures.Models.csproj b/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures.Models/Api.Data.MySql.StoredProcedures.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures.Models/Api.Data.MySql.StoredProcedures.Models.csproj
+++ b/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures.Models/Api.Data.MySql.StoredProcedures.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/Dockerfile.Local b/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/Dockerfile.Local
index e3651ec7..b1585bdc 100644
--- a/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/Dockerfile.Local
+++ b/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.MySql.StoredProcedures.dll"]
\ No newline at end of file
diff --git a/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/appsettings.Development.json b/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/appsettings.Development.json
+++ b/Api.Data.MySql.StoredProcedures/Api.Data.MySql.StoredProcedures/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.MySql.StoredProcedures/Dockerfile b/Api.Data.MySql.StoredProcedures/Dockerfile
index 81df7ff6..feba0098 100644
--- a/Api.Data.MySql.StoredProcedures/Dockerfile
+++ b/Api.Data.MySql.StoredProcedures/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql.Views/.docker/docker-compose.yml b/Api.Data.MySql.Views/.docker/docker-compose.yml
index 8a5c7578..4f52ca85 100644
--- a/Api.Data.MySql.Views/.docker/docker-compose.yml
+++ b/Api.Data.MySql.Views/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.MySql.Views/.github/workflows/build-and-deploy.yml b/Api.Data.MySql.Views/.github/workflows/build-and-deploy.yml
index 2466d7bf..7668a2b9 100644
--- a/Api.Data.MySql.Views/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.MySql.Views/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.MySql.Views
IMAGE_NAME: api.data.mysql.views
SERVICE_NAME: api-data-mysql-views
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.MySql.Views/.kubernetes/auth-sql-secret.yaml b/Api.Data.MySql.Views/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.MySql.Views/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.MySql.Views/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.MySql.Views/.kubernetes/configmap.yaml b/Api.Data.MySql.Views/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.MySql.Views/.kubernetes/configmap.yaml
+++ b/Api.Data.MySql.Views/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.MySql.Views/.kubernetes/deployment.yaml b/Api.Data.MySql.Views/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.MySql.Views/.kubernetes/deployment.yaml
+++ b/Api.Data.MySql.Views/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.MySql.Views/Api.Data.MySql.Views.Models/Api.Data.MySql.Views.Models.csproj b/Api.Data.MySql.Views/Api.Data.MySql.Views.Models/Api.Data.MySql.Views.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.MySql.Views/Api.Data.MySql.Views.Models/Api.Data.MySql.Views.Models.csproj
+++ b/Api.Data.MySql.Views/Api.Data.MySql.Views.Models/Api.Data.MySql.Views.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.MySql.Views/Api.Data.MySql.Views/Dockerfile.Local b/Api.Data.MySql.Views/Api.Data.MySql.Views/Dockerfile.Local
index bac8ec3f..a71eddd5 100644
--- a/Api.Data.MySql.Views/Api.Data.MySql.Views/Dockerfile.Local
+++ b/Api.Data.MySql.Views/Api.Data.MySql.Views/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.MySql.Views.dll"]
\ No newline at end of file
diff --git a/Api.Data.MySql.Views/Api.Data.MySql.Views/appsettings.Development.json b/Api.Data.MySql.Views/Api.Data.MySql.Views/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.MySql.Views/Api.Data.MySql.Views/appsettings.Development.json
+++ b/Api.Data.MySql.Views/Api.Data.MySql.Views/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.MySql.Views/Dockerfile b/Api.Data.MySql.Views/Dockerfile
index 9e00750f..7922740b 100644
--- a/Api.Data.MySql.Views/Dockerfile
+++ b/Api.Data.MySql.Views/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql/.docker/docker-compose.yml b/Api.Data.MySql/.docker/docker-compose.yml
index e1757ea8..05a59213 100644
--- a/Api.Data.MySql/.docker/docker-compose.yml
+++ b/Api.Data.MySql/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.MySql/.github/workflows/build-and-deploy.yml b/Api.Data.MySql/.github/workflows/build-and-deploy.yml
index cba9bb65..9cd43178 100644
--- a/Api.Data.MySql/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.MySql/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.MySql
IMAGE_NAME: api.data.mysql
SERVICE_NAME: api-data-mysql
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.MySql/.kubernetes/auth-sql-secret.yaml b/Api.Data.MySql/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.MySql/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.MySql/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.MySql/.kubernetes/configmap.yaml b/Api.Data.MySql/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.MySql/.kubernetes/configmap.yaml
+++ b/Api.Data.MySql/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.MySql/.kubernetes/deployment.yaml b/Api.Data.MySql/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.MySql/.kubernetes/deployment.yaml
+++ b/Api.Data.MySql/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.MySql/Api.Data.MySql.Models/Api.Data.MySql.Models.csproj b/Api.Data.MySql/Api.Data.MySql.Models/Api.Data.MySql.Models.csproj
index 1a34a185..0c881493 100644
--- a/Api.Data.MySql/Api.Data.MySql.Models/Api.Data.MySql.Models.csproj
+++ b/Api.Data.MySql/Api.Data.MySql.Models/Api.Data.MySql.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.MySql/Api.Data.MySql/Dockerfile.Local b/Api.Data.MySql/Api.Data.MySql/Dockerfile.Local
index 2c0d1470..daf3f124 100644
--- a/Api.Data.MySql/Api.Data.MySql/Dockerfile.Local
+++ b/Api.Data.MySql/Api.Data.MySql/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.MySql.dll"]
\ No newline at end of file
diff --git a/Api.Data.MySql/Api.Data.MySql/appsettings.Development.json b/Api.Data.MySql/Api.Data.MySql/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.MySql/Api.Data.MySql/appsettings.Development.json
+++ b/Api.Data.MySql/Api.Data.MySql/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.MySql/Dockerfile b/Api.Data.MySql/Dockerfile
index d88ccf17..680e6c3b 100644
--- a/Api.Data.MySql/Dockerfile
+++ b/Api.Data.MySql/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.MySql/README.md b/Api.Data.MySql/README.md
index 73a6b67a..6d1dd5ec 100644
--- a/Api.Data.MySql/README.md
+++ b/Api.Data.MySql/README.md
@@ -81,7 +81,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": null,
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
@@ -125,7 +125,7 @@ services:
```
## Kubernetes
-Added the `%SERVICE_NAME%-secret` for the connectionstring to the `deployment.yaml`.
+Added the `auth-sql-secret.yaml` for the connectionstring to the `deployment.yaml`.
```json
spec:
@@ -145,6 +145,8 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
+ DOTNET_EF_TOOLS_VERSION: "10.0"
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
@@ -157,33 +159,56 @@ Additionally, this step has been added to ensure database migrations are applied
- name: Database Migration & User
shell: pwsh
run: |
- $env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName;
- $env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort;
- $env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
+ $env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
+ $env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
+ $env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
+ --no-build `
+ --configuration Release `
+ --startup-project $env:APP_NAME `
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
- apt-get update;
- apt-get install -y mysql-client;
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
- $userExists = mysql --batch -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '$env:SQL_USER');" $env:SQL_MIGRATION_CONNECTIONSTRING;
+ $userExists = mysql `
+ --host $env:SQL_HOST `
+ --port $env:SQL_PORT `
+ --user $env:SQL_ADMIN_USER `
+ --ssl-mode=REQUIRED `
+ -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '$env:SQL_USER');";
if ($userExists -eq 0)
{
- mysql --connect-expired-password -e " `
- CREATE USER '$env:SQL_USER'@'%' IDENTIFIED BY '$env:SQL_PASSWORD'; `
- GRANT SELECT, INSERT, UPDATE, DELETE ON $database.* TO '$env:SQL_USER'@'%'; `
- FLUSH PRIVILEGES;" $env:SQL_MIGRATION_CONNECTIONSTRING;
+ mysql `
+ --host $env:SQL_HOST `
+ --port $env:SQL_PORT `
+ --user $env:SQL_ADMIN_USER `
+ --ssl-mode=REQUIRED `
+ -e "CREATE USER '$env:SQL_USER'@'%' IDENTIFIED BY '$env:SQL_PASSWORD'; GRANT SELECT, INSERT, UPDATE, DELETE ON $env:SQL_NAME.* TO '$env:SQL_USER'@'%'; FLUSH PRIVILEGES;";
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
}
+
+ echo "SQL_HOST=$env:SQL_HOST" >> $env:GITHUB_ENV;
+ echo "SQL_PORT=$env:SQL_PORT" >> $env:GITHUB_ENV;
+```
+
+Last, before applying the new Kubernetes templates, these environmental variables must be set.
+
+```powershell
+$env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
```
-Last, an additional template has been added to the deployment for storing the application connectionstring in a Kuberntes secret.
+Finally, apply the templates.
diff --git a/Api.Data.PostgreSQL.Spatial/.github/workflows/build-and-deploy.yml b/Api.Data.PostgreSQL.Spatial/.github/workflows/build-and-deploy.yml
index 070e0c51..8337fcc2 100644
--- a/Api.Data.PostgreSQL.Spatial/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.PostgreSQL.Spatial/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.PostgreSQL.Spatial
IMAGE_NAME: api.data.postgresql.spatial
SERVICE_NAME: api-data-postgresql-spatial
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-postgres-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,68 +65,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
@@ -136,10 +132,14 @@ jobs:
$env:SQL_ADMIN_USER = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].username" -o tsv;
$env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Prefer;Trust Server Certificate=true";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = $env:SQL_MIGRATION_CONNECTIONSTRING;
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
@@ -220,7 +220,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -228,6 +228,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.PostgreSQL.Spatial/.kubernetes/auth-sql-secret.yaml b/Api.Data.PostgreSQL.Spatial/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.PostgreSQL.Spatial/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.PostgreSQL.Spatial/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.PostgreSQL.Spatial/.kubernetes/configmap.yaml b/Api.Data.PostgreSQL.Spatial/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.PostgreSQL.Spatial/.kubernetes/configmap.yaml
+++ b/Api.Data.PostgreSQL.Spatial/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.PostgreSQL.Spatial/.kubernetes/deployment.yaml b/Api.Data.PostgreSQL.Spatial/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.PostgreSQL.Spatial/.kubernetes/deployment.yaml
+++ b/Api.Data.PostgreSQL.Spatial/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial.Models/Api.Data.PostgreSQL.Spatial.Models.csproj b/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial.Models/Api.Data.PostgreSQL.Spatial.Models.csproj
index 9b2d874d..9fb055c4 100644
--- a/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial.Models/Api.Data.PostgreSQL.Spatial.Models.csproj
+++ b/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial.Models/Api.Data.PostgreSQL.Spatial.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial/Dockerfile.Local b/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial/Dockerfile.Local
index 9e8b385b..67d117e3 100644
--- a/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial/Dockerfile.Local
+++ b/Api.Data.PostgreSQL.Spatial/Api.Data.PostgreSQL.Spatial/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.PostgreSQL.Spatial.dll"]
\ No newline at end of file
diff --git a/Api.Data.PostgreSQL.Spatial/Dockerfile b/Api.Data.PostgreSQL.Spatial/Dockerfile
index a1c9d769..5231bcb9 100644
--- a/Api.Data.PostgreSQL.Spatial/Dockerfile
+++ b/Api.Data.PostgreSQL.Spatial/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.PostgreSQL/.github/workflows/build-and-deploy.yml b/Api.Data.PostgreSQL/.github/workflows/build-and-deploy.yml
index 2e82e0f1..1c3f79d0 100644
--- a/Api.Data.PostgreSQL/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.PostgreSQL/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.PostgreSQL
IMAGE_NAME: api.data.postgresql
SERVICE_NAME: api-data-postgresql
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-postgres-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,80 +65,81 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "5432";
$env:SQL_ADMIN_USER = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].username" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Prefer;Trust Server Certificate=true";
+ $env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Require;Trust Server Certificate=true";
+
+ $env:DATA__CONNECTIONSTRING = $env:SQL_MIGRATION_CONNECTIONSTRING;
- dotnet ef database update `
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
@@ -182,7 +182,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_USER;Password=$env:SQL_PASSWORD;SSL Mode=Prefer;Trust Server Certificate=true";
+ $env:SQL_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_USER;Password=$env:SQL_PASSWORD;SSL Mode=Require;Trust Server Certificate=true";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -220,7 +220,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -228,6 +228,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml b/Api.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.PostgreSQL/.kubernetes/configmap.yaml b/Api.Data.PostgreSQL/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.PostgreSQL/.kubernetes/configmap.yaml
+++ b/Api.Data.PostgreSQL/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.PostgreSQL/.kubernetes/deployment.yaml b/Api.Data.PostgreSQL/.kubernetes/deployment.yaml
index 7e8688ef..d910429c 100644
--- a/Api.Data.PostgreSQL/.kubernetes/deployment.yaml
+++ b/Api.Data.PostgreSQL/.kubernetes/deployment.yaml
@@ -79,6 +79,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.Data.PostgreSQL/Api.Data.PostgreSQL.Models/Api.Data.PostgreSQL.Models.csproj b/Api.Data.PostgreSQL/Api.Data.PostgreSQL.Models/Api.Data.PostgreSQL.Models.csproj
index 9b2d874d..9fb055c4 100644
--- a/Api.Data.PostgreSQL/Api.Data.PostgreSQL.Models/Api.Data.PostgreSQL.Models.csproj
+++ b/Api.Data.PostgreSQL/Api.Data.PostgreSQL.Models/Api.Data.PostgreSQL.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.PostgreSQL/Api.Data.PostgreSQL/Dockerfile.Local b/Api.Data.PostgreSQL/Api.Data.PostgreSQL/Dockerfile.Local
index e3fe4a49..2ed1cd4f 100644
--- a/Api.Data.PostgreSQL/Api.Data.PostgreSQL/Dockerfile.Local
+++ b/Api.Data.PostgreSQL/Api.Data.PostgreSQL/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.PostgreSQL.dll"]
\ No newline at end of file
diff --git a/Api.Data.PostgreSQL/Dockerfile b/Api.Data.PostgreSQL/Dockerfile
index 754207ea..5afe6e4b 100644
--- a/Api.Data.PostgreSQL/Dockerfile
+++ b/Api.Data.PostgreSQL/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.PostgreSQL/README.md b/Api.Data.PostgreSQL/README.md
index 982e730e..f2fa31cd 100644
--- a/Api.Data.PostgreSQL/README.md
+++ b/Api.Data.PostgreSQL/README.md
@@ -81,7 +81,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": null,
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
@@ -123,7 +123,7 @@ services:
```
## Kubernetes
-Added the `%SERVICE_NAME%-secret` for the connectionstring to the `deployment.yaml`.
+Added the `auth-sql-secret.yaml` for the connectionstring to the `deployment.yaml`.
```json
spec:
@@ -143,6 +143,8 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
+ DOTNET_EF_TOOLS_VERSION: "10.0"
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
SQL_NAME: nanoDb
SQL_USER: api-data-postgres-user
SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
@@ -160,18 +162,19 @@ Additionally, this step has been added to ensure database migrations are applied
$env:SQL_ADMIN_USER = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].username" -o tsv;
$env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Prefer;Trust Server Certificate=true";
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
+ $env:DATA__CONNECTIONSTRING = $env:SQL_MIGRATION_CONNECTIONSTRING;
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
+ --no-build `
+ --configuration Release `
+ --startup-project $env:APP_NAME `
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
-
- apt-get update
- apt-get install -y postgresql-client
$userExists = psql "$env:SQL_MIGRATION_CONNECTIONSTRING" `
-tAc "SELECT 1 FROM pg_roles WHERE rolname='$env:SQL_USER';"
@@ -199,6 +202,15 @@ Additionally, this step has been added to ensure database migrations are applied
psql "$env:SQL_MIGRATION_CONNECTIONSTRING" `
-c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO $env:SQL_USER;"
}
+
+ echo "SQL_HOST=$env:SQL_HOST" >> $env:GITHUB_ENV;
+ echo "SQL_PORT=$env:SQL_PORT" >> $env:GITHUB_ENV;
+```
+
+Last, before applying the new Kubernetes templates, these environmental variables must be set.
+
+```powershell
+$env:SQL_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_USER;Password=$env:SQL_PASSWORD;SSL Mode=Require;Trust Server Certificate=true";
```
-Last, an additional template has been added to the deployment for storing the application connectionstring in a Kuberntes secret.
+Finally, apply the templates.
diff --git a/Api.Data.Repository.AutoSave/.docker/docker-compose.yml b/Api.Data.Repository.AutoSave/.docker/docker-compose.yml
index 9b69f42b..3b06ee7b 100644
--- a/Api.Data.Repository.AutoSave/.docker/docker-compose.yml
+++ b/Api.Data.Repository.AutoSave/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Repository.AutoSave/.github/workflows/build-and-deploy.yml b/Api.Data.Repository.AutoSave/.github/workflows/build-and-deploy.yml
index cac9c331..531a6e7f 100644
--- a/Api.Data.Repository.AutoSave/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Repository.AutoSave/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Repository.AutoSave
IMAGE_NAME: api.data.repository.autosave
SERVICE_NAME: api-data-repository-autosave
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Repository.AutoSave/.kubernetes/auth-sql-secret.yaml b/Api.Data.Repository.AutoSave/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Repository.AutoSave/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Repository.AutoSave/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Repository.AutoSave/.kubernetes/configmap.yaml b/Api.Data.Repository.AutoSave/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Repository.AutoSave/.kubernetes/configmap.yaml
+++ b/Api.Data.Repository.AutoSave/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Repository.AutoSave/.kubernetes/deployment.yaml b/Api.Data.Repository.AutoSave/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.Repository.AutoSave/.kubernetes/deployment.yaml
+++ b/Api.Data.Repository.AutoSave/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave.Models/Api.Data.Repository.AutoSave.Models.csproj b/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave.Models/Api.Data.Repository.AutoSave.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave.Models/Api.Data.Repository.AutoSave.Models.csproj
+++ b/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave.Models/Api.Data.Repository.AutoSave.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/Dockerfile.Local b/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/Dockerfile.Local
index 265ee7c3..c7eec079 100644
--- a/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/Dockerfile.Local
+++ b/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Repository.AutoSave.dll"]
\ No newline at end of file
diff --git a/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/appsettings.Development.json b/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/appsettings.Development.json
+++ b/Api.Data.Repository.AutoSave/Api.Data.Repository.AutoSave/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Repository.AutoSave/Dockerfile b/Api.Data.Repository.AutoSave/Dockerfile
index 3c02c42d..04f4949f 100644
--- a/Api.Data.Repository.AutoSave/Dockerfile
+++ b/Api.Data.Repository.AutoSave/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.Repository.Includes/.docker/docker-compose.yml b/Api.Data.Repository.Includes/.docker/docker-compose.yml
index 98336e73..bb0a018c 100644
--- a/Api.Data.Repository.Includes/.docker/docker-compose.yml
+++ b/Api.Data.Repository.Includes/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Repository.Includes/.github/workflows/build-and-deploy.yml b/Api.Data.Repository.Includes/.github/workflows/build-and-deploy.yml
index 8638dea7..0ce35b2f 100644
--- a/Api.Data.Repository.Includes/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Repository.Includes/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Repository.Includes
IMAGE_NAME: api.data.repository.includes
SERVICE_NAME: api-data-repository-includes
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Repository.Includes/.kubernetes/auth-sql-secret.yaml b/Api.Data.Repository.Includes/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Repository.Includes/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Repository.Includes/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Repository.Includes/.kubernetes/configmap.yaml b/Api.Data.Repository.Includes/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Repository.Includes/.kubernetes/configmap.yaml
+++ b/Api.Data.Repository.Includes/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Repository.Includes/.kubernetes/deployment.yaml b/Api.Data.Repository.Includes/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.Repository.Includes/.kubernetes/deployment.yaml
+++ b/Api.Data.Repository.Includes/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Repository.Includes/Api.Data.Repository.Includes.Models/Api.Data.Repository.Includes.Models.csproj b/Api.Data.Repository.Includes/Api.Data.Repository.Includes.Models/Api.Data.Repository.Includes.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Repository.Includes/Api.Data.Repository.Includes.Models/Api.Data.Repository.Includes.Models.csproj
+++ b/Api.Data.Repository.Includes/Api.Data.Repository.Includes.Models/Api.Data.Repository.Includes.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Repository.Includes/Api.Data.Repository.Includes/Dockerfile.Local b/Api.Data.Repository.Includes/Api.Data.Repository.Includes/Dockerfile.Local
index f67686a8..d346cc6b 100644
--- a/Api.Data.Repository.Includes/Api.Data.Repository.Includes/Dockerfile.Local
+++ b/Api.Data.Repository.Includes/Api.Data.Repository.Includes/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Repository.Includes.dll"]
\ No newline at end of file
diff --git a/Api.Data.Repository.Includes/Api.Data.Repository.Includes/appsettings.Development.json b/Api.Data.Repository.Includes/Api.Data.Repository.Includes/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.Repository.Includes/Api.Data.Repository.Includes/appsettings.Development.json
+++ b/Api.Data.Repository.Includes/Api.Data.Repository.Includes/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Repository.Includes/Dockerfile b/Api.Data.Repository.Includes/Dockerfile
index 51c6edab..25101994 100644
--- a/Api.Data.Repository.Includes/Dockerfile
+++ b/Api.Data.Repository.Includes/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.SoftDelete/.docker/docker-compose.yml b/Api.Data.SoftDelete/.docker/docker-compose.yml
index 2182ed3f..0fbddac4 100644
--- a/Api.Data.SoftDelete/.docker/docker-compose.yml
+++ b/Api.Data.SoftDelete/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.SoftDelete/.github/workflows/build-and-deploy.yml b/Api.Data.SoftDelete/.github/workflows/build-and-deploy.yml
index 957cec57..8de44e0c 100644
--- a/Api.Data.SoftDelete/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.SoftDelete/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.SoftDelete
IMAGE_NAME: api.data.softdelete
SERVICE_NAME: api-data-softdelete
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.SoftDelete/.kubernetes/auth-sql-secret.yaml b/Api.Data.SoftDelete/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.SoftDelete/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.SoftDelete/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.SoftDelete/.kubernetes/configmap.yaml b/Api.Data.SoftDelete/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.SoftDelete/.kubernetes/configmap.yaml
+++ b/Api.Data.SoftDelete/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.SoftDelete/.kubernetes/deployment.yaml b/Api.Data.SoftDelete/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.SoftDelete/.kubernetes/deployment.yaml
+++ b/Api.Data.SoftDelete/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.SoftDelete/Api.Data.SoftDelete.Models/Api.Data.SoftDelete.Models.csproj b/Api.Data.SoftDelete/Api.Data.SoftDelete.Models/Api.Data.SoftDelete.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.SoftDelete/Api.Data.SoftDelete.Models/Api.Data.SoftDelete.Models.csproj
+++ b/Api.Data.SoftDelete/Api.Data.SoftDelete.Models/Api.Data.SoftDelete.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.SoftDelete/Api.Data.SoftDelete/Dockerfile.Local b/Api.Data.SoftDelete/Api.Data.SoftDelete/Dockerfile.Local
index f0398733..00faa108 100644
--- a/Api.Data.SoftDelete/Api.Data.SoftDelete/Dockerfile.Local
+++ b/Api.Data.SoftDelete/Api.Data.SoftDelete/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.SoftDelete.dll"]
\ No newline at end of file
diff --git a/Api.Data.SoftDelete/Api.Data.SoftDelete/appsettings.Development.json b/Api.Data.SoftDelete/Api.Data.SoftDelete/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.SoftDelete/Api.Data.SoftDelete/appsettings.Development.json
+++ b/Api.Data.SoftDelete/Api.Data.SoftDelete/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.SoftDelete/Dockerfile b/Api.Data.SoftDelete/Dockerfile
index 4c606a9e..a494a421 100644
--- a/Api.Data.SoftDelete/Dockerfile
+++ b/Api.Data.SoftDelete/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.SqLite/.github/workflows/build-and-deploy.yml b/Api.Data.SqLite/.github/workflows/build-and-deploy.yml
index 98ad1455..3e521bd1 100644
--- a/Api.Data.SqLite/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.SqLite/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,30 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
env:
APP_NAME: Api.Data.SqLite
IMAGE_NAME: api.data.sqlite
SERVICE_NAME: api-data-sqlite
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,23 +33,20 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
- SQL_NAME: nanoDb
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_SIZE: 10Gi
- SQL_MIGRATION_CONNECTIONSTRING: "Data Source=/mnt/data/{{ env.SQL_NAME }}.sqlite"
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -65,80 +59,64 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
- shell: pwsh
- run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- name: Publish NuGet
shell: pwsh
run: |
$nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Database Migration
+ - name: Build & Push Image
shell: pwsh
run: |
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- if ($LastExitCode -ne 0)
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
+ if ($LastExitCode -ne 0)
{
throw "error";
- };
+ };
+
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
- name: Kubernetes Deploy
shell: pwsh
@@ -186,7 +164,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -194,6 +172,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.SqLite/.kubernetes/configmap.yaml b/Api.Data.SqLite/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.SqLite/.kubernetes/configmap.yaml
+++ b/Api.Data.SqLite/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.SqLite/.kubernetes/data-pvc.yaml b/Api.Data.SqLite/.kubernetes/data-pvc.yaml
index 0b9d4415..00bca640 100644
--- a/Api.Data.SqLite/.kubernetes/data-pvc.yaml
+++ b/Api.Data.SqLite/.kubernetes/data-pvc.yaml
@@ -8,4 +8,4 @@ spec:
storageClassName: %SERVICE_NAME%-data-storage-class
resources:
requests:
- storage: %DATA_SIZE%
\ No newline at end of file
+ storage: %SQL_SIZE%
\ No newline at end of file
diff --git a/Api.Data.SqLite/.kubernetes/data-storageclass.yaml b/Api.Data.SqLite/.kubernetes/data-storageclass.yaml
index 47530cdc..2f66693c 100644
--- a/Api.Data.SqLite/.kubernetes/data-storageclass.yaml
+++ b/Api.Data.SqLite/.kubernetes/data-storageclass.yaml
@@ -2,7 +2,7 @@ apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: %SERVICE_NAME%-data-storage-class
-provisioner: kubernetes.io/azure-disk
+provisioner: disk.csi.azure.com
parameters:
storageaccounttype: Standard_LRS
kind: Managed
diff --git a/Api.Data.SqLite/.kubernetes/deployment.yaml b/Api.Data.SqLite/.kubernetes/deployment.yaml
index 354c85fb..fd8b1951 100644
--- a/Api.Data.SqLite/.kubernetes/deployment.yaml
+++ b/Api.Data.SqLite/.kubernetes/deployment.yaml
@@ -80,6 +80,3 @@ spec:
- name: %SERVICE_NAME%-volume
persistentVolumeClaim:
claimName: %SERVICE_NAME%-pvc
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.SqLite/Api.Data.SqLite.Models/Api.Data.SqLite.Models.csproj b/Api.Data.SqLite/Api.Data.SqLite.Models/Api.Data.SqLite.Models.csproj
index 796675d7..4fd03943 100644
--- a/Api.Data.SqLite/Api.Data.SqLite.Models/Api.Data.SqLite.Models.csproj
+++ b/Api.Data.SqLite/Api.Data.SqLite.Models/Api.Data.SqLite.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.SqLite/Api.Data.SqLite/Dockerfile.Local b/Api.Data.SqLite/Api.Data.SqLite/Dockerfile.Local
index 28ad6e11..0dd334f1 100644
--- a/Api.Data.SqLite/Api.Data.SqLite/Dockerfile.Local
+++ b/Api.Data.SqLite/Api.Data.SqLite/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.SqLite.dll"]
\ No newline at end of file
diff --git a/Api.Data.SqLite/Api.Data.SqLite/appsettings.Development.json b/Api.Data.SqLite/Api.Data.SqLite/appsettings.Development.json
index 8927ff99..29091fa5 100644
--- a/Api.Data.SqLite/Api.Data.SqLite/appsettings.Development.json
+++ b/Api.Data.SqLite/Api.Data.SqLite/appsettings.Development.json
@@ -1,5 +1,3 @@
{
- "Data": {
- "StartupAction": "Migrate"
- }
+
}
\ No newline at end of file
diff --git a/Api.Data.SqLite/Api.Data.SqLite/appsettings.json b/Api.Data.SqLite/Api.Data.SqLite/appsettings.json
index 496df4fb..8e51eb81 100644
--- a/Api.Data.SqLite/Api.Data.SqLite/appsettings.json
+++ b/Api.Data.SqLite/Api.Data.SqLite/appsettings.json
@@ -20,7 +20,7 @@
"BulkBatchSize": 500,
"BulkBatchDelay": 1000,
"QueryRetryCount": 0,
- "StartupAction": "None",
+ "StartupAction": "Migrate",
"UseLazyLoading": false,
"UseSensitiveDataLogging": false,
"QuerySplittingBehavior": "SingleQuery",
diff --git a/Api.Data.SqLite/Dockerfile b/Api.Data.SqLite/Dockerfile
index 8c1d942b..aa01ca87 100644
--- a/Api.Data.SqLite/Dockerfile
+++ b/Api.Data.SqLite/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.SqLite/README.md b/Api.Data.SqLite/README.md
index 0884a1cc..9aef9986 100644
--- a/Api.Data.SqLite/README.md
+++ b/Api.Data.SqLite/README.md
@@ -81,7 +81,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": "Data Source=/data/nanoDb.sqlite",
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
@@ -92,13 +92,7 @@ Configured the application with the necessary data setup.
}
```
-...and `appsettings.Development.json`
-
-```json
-"Data": {
- "StartupAction": "Migrate"
-}
-```
+> ⚠️ **Notice:** `StartupAction` is set to `migrate` in all environments. This may cause the pod to restart during the initial deployment.
## Docker Compose
Added SqLite as a service dependency in `docker-compose.yml`.
@@ -134,34 +128,7 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
- SQL_NAME: nanoDb
SQL_SIZE: 10Gi
- SQL_CONNECTIONSTRING: "Data Source=/mnt/data/{{ env.nanoDb }}.sqlite"
-```
-
-Additionally, this step has been added to ensure database migrations are applied.
-
-```yaml
-- name: Database Migration
- shell: pwsh
- run: |
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
```
Deployment commands have also been updated to apply each of the new Kubernetes templates.
-
-```powershell
-Get-Content .kubernetes/{resource-name}.yaml `
- | foreach { [Environment]::ExpandEnvironmentVariables($_) } `
- | Set-Content .kubernetes/{resource-name}.tmp.yaml;
-
-sudo kubectl apply -f .kubernetes/{resource-name}.tmp.yaml;
-```
diff --git a/Api.Data.SqlServer.Spatial/.github/workflows/build-and-deploy.yml b/Api.Data.SqlServer.Spatial/.github/workflows/build-and-deploy.yml
index e7532a1d..8922d769 100644
--- a/Api.Data.SqlServer.Spatial/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.SqlServer.Spatial/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.SqlServer.Spatial
IMAGE_NAME: api.data.sqlserver.spatial
SERVICE_NAME: api-data-sqlserver-spatial
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-sqlserver-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,80 +65,80 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "1433"
$env:SQL_ADMIN_USER = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].administratorLogin" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
@@ -153,7 +152,7 @@ jobs:
-S "$env:SQL_HOST,$env:SQL_PORT" `
-U $env:SQL_ADMIN_USER `
-P $env:SQL_ADMIN_PASSWORD `
- -d master `
+ -d main `
-h -1 `
-Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
@@ -163,7 +162,7 @@ jobs:
-S "$env:SQL_HOST,$env:SQL_PORT" `
-U $env:SQL_ADMIN_USER `
-P $env:SQL_ADMIN_PASSWORD `
- -d master `
+ -d main `
-Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
};
@@ -231,7 +230,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -239,6 +238,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.SqlServer.Spatial/.kubernetes/auth-sql-secret.yaml b/Api.Data.SqlServer.Spatial/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.SqlServer.Spatial/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.SqlServer.Spatial/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.SqlServer.Spatial/.kubernetes/configmap.yaml b/Api.Data.SqlServer.Spatial/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.SqlServer.Spatial/.kubernetes/configmap.yaml
+++ b/Api.Data.SqlServer.Spatial/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.SqlServer.Spatial/.kubernetes/deployment.yaml b/Api.Data.SqlServer.Spatial/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.SqlServer.Spatial/.kubernetes/deployment.yaml
+++ b/Api.Data.SqlServer.Spatial/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial.Models/Api.Data.SqlServer.Spatial.Models.csproj b/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial.Models/Api.Data.SqlServer.Spatial.Models.csproj
index 8c31e7ba..396d24b3 100644
--- a/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial.Models/Api.Data.SqlServer.Spatial.Models.csproj
+++ b/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial.Models/Api.Data.SqlServer.Spatial.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial/Dockerfile.Local b/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial/Dockerfile.Local
index cb81de7f..8b5fa640 100644
--- a/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial/Dockerfile.Local
+++ b/Api.Data.SqlServer.Spatial/Api.Data.SqlServer.Spatial/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.SqlServer.Spatial.dll"]
\ No newline at end of file
diff --git a/Api.Data.SqlServer.Spatial/Dockerfile b/Api.Data.SqlServer.Spatial/Dockerfile
index 1bc24530..e05b9d4b 100644
--- a/Api.Data.SqlServer.Spatial/Dockerfile
+++ b/Api.Data.SqlServer.Spatial/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.SqlServer/.github/workflows/build-and-deploy.yml b/Api.Data.SqlServer/.github/workflows/build-and-deploy.yml
index 370b8153..20874458 100644
--- a/Api.Data.SqlServer/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.SqlServer/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.SqlServer
IMAGE_NAME: api.data.sqlserver
SERVICE_NAME: api-data-sqlserver
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-sqlserver-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,80 +65,80 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "1433"
$env:SQL_ADMIN_USER = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].administratorLogin" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
@@ -153,7 +152,7 @@ jobs:
-S "$env:SQL_HOST,$env:SQL_PORT" `
-U $env:SQL_ADMIN_USER `
-P $env:SQL_ADMIN_PASSWORD `
- -d master `
+ -d main `
-h -1 `
-Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
@@ -163,7 +162,7 @@ jobs:
-S "$env:SQL_HOST,$env:SQL_PORT" `
-U $env:SQL_ADMIN_USER `
-P $env:SQL_ADMIN_PASSWORD `
- -d master `
+ -d main `
-Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
};
@@ -231,7 +230,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -239,6 +238,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.SqlServer/.kubernetes/auth-sql-secret.yaml b/Api.Data.SqlServer/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.SqlServer/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.SqlServer/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.SqlServer/.kubernetes/configmap.yaml b/Api.Data.SqlServer/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.SqlServer/.kubernetes/configmap.yaml
+++ b/Api.Data.SqlServer/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.SqlServer/.kubernetes/deployment.yaml b/Api.Data.SqlServer/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.SqlServer/.kubernetes/deployment.yaml
+++ b/Api.Data.SqlServer/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.SqlServer/Api.Data.SqlServer.Models/Api.Data.SqlServer.Models.csproj b/Api.Data.SqlServer/Api.Data.SqlServer.Models/Api.Data.SqlServer.Models.csproj
index 8c31e7ba..396d24b3 100644
--- a/Api.Data.SqlServer/Api.Data.SqlServer.Models/Api.Data.SqlServer.Models.csproj
+++ b/Api.Data.SqlServer/Api.Data.SqlServer.Models/Api.Data.SqlServer.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.SqlServer/Api.Data.SqlServer/Dockerfile.Local b/Api.Data.SqlServer/Api.Data.SqlServer/Dockerfile.Local
index 8297641c..4cae4ffe 100644
--- a/Api.Data.SqlServer/Api.Data.SqlServer/Dockerfile.Local
+++ b/Api.Data.SqlServer/Api.Data.SqlServer/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.SqlServer.dll"]
\ No newline at end of file
diff --git a/Api.Data.SqlServer/Dockerfile b/Api.Data.SqlServer/Dockerfile
index e140c4f8..d260d7a1 100644
--- a/Api.Data.SqlServer/Dockerfile
+++ b/Api.Data.SqlServer/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Data.SqlServer/README.md b/Api.Data.SqlServer/README.md
index c1286d17..4bfaafca 100644
--- a/Api.Data.SqlServer/README.md
+++ b/Api.Data.SqlServer/README.md
@@ -81,7 +81,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": null,
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
@@ -123,7 +123,7 @@ services:
```
## Kubernetes
-Added the `%SERVICE_NAME%-secret` for the connectionstring to the `deployment.yaml`.
+Added the `auth-sql-secret.yaml` for the connectionstring to the `deployment.yaml`.
```json
spec:
@@ -143,6 +143,8 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
+ DOTNET_EF_TOOLS_VERSION: "10.0"
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
SQL_NAME: nanoDb
SQL_USER: api-data-sqlserver-user
SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
@@ -158,12 +160,15 @@ Additionally, this step has been added to ensure database migrations are applied
$env:SQL_HOST = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "1433"
$env:SQL_ADMIN_USER = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].administratorLogin" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
+ --no-build `
+ --configuration Release `
+ --startup-project $env:APP_NAME `
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
@@ -174,50 +179,51 @@ Additionally, this step has been added to ensure database migrations are applied
apt-get install -y mssql-tools unixodbc-dev
$loginExists = sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d master `
- -h -1 `
- -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d main `
+ -h -1 `
+ -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
if ($loginExists -eq 0)
{
sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d master `
- -Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d main `
+ -Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
};
$userExists = sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d $env:SQL_NAME `
- -h -1 `
- -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.database_principals WHERE name = '$env:SQL_USER';"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d $env:SQL_NAME `
+ -h -1 `
+ -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.database_principals WHERE name = '$env:SQL_USER';"
if ($userExists -eq 0)
{
sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d $env:SQL_NAME `
- -Q "CREATE USER [$env:SQL_USER] FOR LOGIN [$env:SQL_USER];
- ALTER ROLE db_datareader ADD MEMBER [$env:SQL_USER];
- ALTER ROLE db_datawriter ADD MEMBER [$env:SQL_USER];"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d $env:SQL_NAME `
+ -Q "CREATE USER [$env:SQL_USER] FOR LOGIN [$env:SQL_USER];
+ ALTER ROLE db_datareader ADD MEMBER [$env:SQL_USER];
+ ALTER ROLE db_datawriter ADD MEMBER [$env:SQL_USER];"
};
+
+ echo "SQL_HOST=$env:SQL_HOST" >> $env:GITHUB_ENV;
+ echo "SQL_PORT=$env:SQL_PORT" >> $env:GITHUB_ENV;
```
-Last, the application connectionstring must be added in a secret in Kuberntes. The `Kubernetes Deploy` step has been updated with the following.
+Last, before applying the new Kubernetes templates, these environmental variables must be set.
-```yaml
-sudo kubectl create secret generic $env:SERVICE_NAME-data-secret ` --from-literal=data-connectionstring=$env:DATA_CONNECTIONSTRING --save-config --dry-run=client -o yaml | sudo kubectl apply -f -;
-if ($LastExitCode -ne 0)
-{
- throw "error";
-};
+```powershell
+$env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_USER;Password=$env:SQL_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
```
+
+Finally, the templates can be applied.
diff --git a/Api.Data.Triggers/.docker/docker-compose.yml b/Api.Data.Triggers/.docker/docker-compose.yml
index 1bd3d4c3..b7e371df 100644
--- a/Api.Data.Triggers/.docker/docker-compose.yml
+++ b/Api.Data.Triggers/.docker/docker-compose.yml
@@ -20,11 +20,8 @@ services:
networks:
- network
environment:
- MYSQL_USER: sa
- MYSQL_PASSWORD: myPassword_123
- MYSQL_ROOT_PASSWORD: myPassword_123
- MYSQL_DATABASE: nanoDb
MYSQL_ROOT_HOST: '%'
+ MYSQL_ROOT_PASSWORD: myPassword_123
networks:
network:
diff --git a/Api.Data.Triggers/.github/workflows/build-and-deploy.yml b/Api.Data.Triggers/.github/workflows/build-and-deploy.yml
index 0cbf7483..ba28c013 100644
--- a/Api.Data.Triggers/.github/workflows/build-and-deploy.yml
+++ b/Api.Data.Triggers/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Data.Triggers
IMAGE_NAME: api.data.triggers
SERVICE_NAME: api-data-triggers
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_KUBERNETES_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,24 +36,23 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,86 +65,88 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -174,7 +175,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -212,7 +213,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -220,6 +221,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Data.Triggers/.kubernetes/auth-sql-secret.yaml b/Api.Data.Triggers/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Api.Data.Triggers/.kubernetes/auth-sql-secret.yaml
+++ b/Api.Data.Triggers/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Api.Data.Triggers/.kubernetes/configmap.yaml b/Api.Data.Triggers/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Data.Triggers/.kubernetes/configmap.yaml
+++ b/Api.Data.Triggers/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Data.Triggers/.kubernetes/deployment.yaml b/Api.Data.Triggers/.kubernetes/deployment.yaml
index 7e8688ef..a6f04b0f 100644
--- a/Api.Data.Triggers/.kubernetes/deployment.yaml
+++ b/Api.Data.Triggers/.kubernetes/deployment.yaml
@@ -79,6 +79,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Data.Triggers/Api.Data.Triggers.Models/Api.Data.Triggers.Models.csproj b/Api.Data.Triggers/Api.Data.Triggers.Models/Api.Data.Triggers.Models.csproj
index 82be9b94..8fc5868b 100644
--- a/Api.Data.Triggers/Api.Data.Triggers.Models/Api.Data.Triggers.Models.csproj
+++ b/Api.Data.Triggers/Api.Data.Triggers.Models/Api.Data.Triggers.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Data.Triggers/Api.Data.Triggers/Dockerfile.Local b/Api.Data.Triggers/Api.Data.Triggers/Dockerfile.Local
index b8b7fc64..72600b85 100644
--- a/Api.Data.Triggers/Api.Data.Triggers/Dockerfile.Local
+++ b/Api.Data.Triggers/Api.Data.Triggers/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Data.Triggers.dll"]
\ No newline at end of file
diff --git a/Api.Data.Triggers/Api.Data.Triggers/appsettings.Development.json b/Api.Data.Triggers/Api.Data.Triggers/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Api.Data.Triggers/Api.Data.Triggers/appsettings.Development.json
+++ b/Api.Data.Triggers/Api.Data.Triggers/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Api.Data.Triggers/Dockerfile b/Api.Data.Triggers/Dockerfile
index 6f4ffa68..0225e47b 100644
--- a/Api.Data.Triggers/Dockerfile
+++ b/Api.Data.Triggers/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Documentation.Csp/.github/workflows/build-and-deploy.yml b/Api.Documentation.Csp/.github/workflows/build-and-deploy.yml
index 00b3b84b..10b03dd2 100644
--- a/Api.Documentation.Csp/.github/workflows/build-and-deploy.yml
+++ b/Api.Documentation.Csp/.github/workflows/build-and-deploy.yml
@@ -2,35 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Documentation.Csp
IMAGE_NAME: api.documentation.csp
SERVICE_NAME: api-documentation-csp
SUB_DOMAIN_NAME: nano
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_GROUP_DNS: ${{ vars.AZURE_RESOURCE_GROUP_DNS }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,20 +36,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,71 +61,70 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
+ $env:GATEWAY_NAME = kubectl get gateway -n apps -o jsonpath='{.items[0].metadata.name}'
+
$zoneNames = az network dns zone list -g $env:AZURE_GROUP_DNS --query [].name;
$env:ROUTE_HOST_NAMES = @(
@@ -139,8 +135,6 @@ jobs:
}
) -join "`n";
- $env:GATEWAY_NAME = kubectl get gateway -n apps -o jsonpath='{.items[0].metadata.name}'
-
Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
Get-Content .kubernetes/configmap.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/configmap.tmp.yaml;
Get-Content .kubernetes/deployment.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/deployment.tmp.yaml;
@@ -173,7 +167,7 @@ jobs:
}
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -181,6 +175,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Documentation.Csp/.kubernetes/deployment.yaml b/Api.Documentation.Csp/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Documentation.Csp/.kubernetes/deployment.yaml
+++ b/Api.Documentation.Csp/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Documentation.Csp/Api.Documentation.Csp.Models/Api.Documentation.Csp.Models.csproj b/Api.Documentation.Csp/Api.Documentation.Csp.Models/Api.Documentation.Csp.Models.csproj
index 7a4d41f3..5721d8ef 100644
--- a/Api.Documentation.Csp/Api.Documentation.Csp.Models/Api.Documentation.Csp.Models.csproj
+++ b/Api.Documentation.Csp/Api.Documentation.Csp.Models/Api.Documentation.Csp.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Documentation.Csp/Api.Documentation.Csp/Dockerfile.Local b/Api.Documentation.Csp/Api.Documentation.Csp/Dockerfile.Local
index 8f4d7cbf..69031946 100644
--- a/Api.Documentation.Csp/Api.Documentation.Csp/Dockerfile.Local
+++ b/Api.Documentation.Csp/Api.Documentation.Csp/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080 4443
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Documentation.Csp.dll"]
\ No newline at end of file
diff --git a/Api.Documentation.Csp/Dockerfile b/Api.Documentation.Csp/Dockerfile
index 32d43b6b..145a982f 100644
--- a/Api.Documentation.Csp/Dockerfile
+++ b/Api.Documentation.Csp/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Documentation/.github/workflows/build-and-deploy.yml b/Api.Documentation/.github/workflows/build-and-deploy.yml
index 87545d98..8c9d47f6 100644
--- a/Api.Documentation/.github/workflows/build-and-deploy.yml
+++ b/Api.Documentation/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Documentation
IMAGE_NAME: api.documentation
SERVICE_NAME: api-documentation
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
- build-and-deploy:
+ build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Documentation/.kubernetes/configmap.yaml b/Api.Documentation/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Documentation/.kubernetes/configmap.yaml
+++ b/Api.Documentation/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Documentation/.kubernetes/deployment.yaml b/Api.Documentation/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Documentation/.kubernetes/deployment.yaml
+++ b/Api.Documentation/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Documentation/Api.Documentation.Models/Api.Documentation.Models.csproj b/Api.Documentation/Api.Documentation.Models/Api.Documentation.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Documentation/Api.Documentation.Models/Api.Documentation.Models.csproj
+++ b/Api.Documentation/Api.Documentation.Models/Api.Documentation.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Documentation/Api.Documentation/Dockerfile.Local b/Api.Documentation/Api.Documentation/Dockerfile.Local
index 8304fa2a..29c326a8 100644
--- a/Api.Documentation/Api.Documentation/Dockerfile.Local
+++ b/Api.Documentation/Api.Documentation/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Documentation.dll"]
\ No newline at end of file
diff --git a/Api.Documentation/Dockerfile b/Api.Documentation/Dockerfile
index bc41ebbf..d928e41b 100644
--- a/Api.Documentation/Dockerfile
+++ b/Api.Documentation/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Documentation/README.md b/Api.Documentation/README.md
index 49195e45..1f878977 100644
--- a/Api.Documentation/README.md
+++ b/Api.Documentation/README.md
@@ -56,4 +56,3 @@ for the same example endpoint. When set to `true`, Swagger only displays the non
}
}
```
-
diff --git a/Api.ErrorHandling/.github/workflows/build-and-deploy.yml b/Api.ErrorHandling/.github/workflows/build-and-deploy.yml
index 012b1be2..d5b1a272 100644
--- a/Api.ErrorHandling/.github/workflows/build-and-deploy.yml
+++ b/Api.ErrorHandling/.github/workflows/build-and-deploy.yml
@@ -6,14 +6,16 @@ on:
push:
branches:
- master
+ workflow_dispatch:
env:
APP_NAME: Api.ErrorHandling
IMAGE_NAME: api.errorhandling
SERVICE_NAME: api-errorhandling
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
@@ -21,10 +23,6 @@ env:
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
KUBERNETES_NAMESPACE: apps
KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
@@ -37,6 +35,9 @@ env:
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
@@ -46,10 +47,6 @@ jobs:
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ErrorHandling/.kubernetes/configmap.yaml b/Api.ErrorHandling/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ErrorHandling/.kubernetes/configmap.yaml
+++ b/Api.ErrorHandling/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ErrorHandling/.kubernetes/deployment.yaml b/Api.ErrorHandling/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ErrorHandling/.kubernetes/deployment.yaml
+++ b/Api.ErrorHandling/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ErrorHandling/Api.ErrorHandling.Models/Api.ErrorHandling.Models.csproj b/Api.ErrorHandling/Api.ErrorHandling.Models/Api.ErrorHandling.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.ErrorHandling/Api.ErrorHandling.Models/Api.ErrorHandling.Models.csproj
+++ b/Api.ErrorHandling/Api.ErrorHandling.Models/Api.ErrorHandling.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ErrorHandling/Api.ErrorHandling/Dockerfile.Local b/Api.ErrorHandling/Api.ErrorHandling/Dockerfile.Local
index 77abb0b3..c4679092 100644
--- a/Api.ErrorHandling/Api.ErrorHandling/Dockerfile.Local
+++ b/Api.ErrorHandling/Api.ErrorHandling/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ErrorHandling.dll"]
\ No newline at end of file
diff --git a/Api.ErrorHandling/Dockerfile b/Api.ErrorHandling/Dockerfile
index de88ee4d..621e601b 100644
--- a/Api.ErrorHandling/Dockerfile
+++ b/Api.ErrorHandling/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml b/Api.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml
index e4a92c54..db8f69b2 100644
--- a/Api.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml
+++ b/Api.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Eventing.RabbitMq
IMAGE_NAME: api.eventing.rabbitmq
SERVICE_NAME: api.eventing-rabbitmq
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Eventing.RabbitMq/.kubernetes/configmap.yaml b/Api.Eventing.RabbitMq/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Eventing.RabbitMq/.kubernetes/configmap.yaml
+++ b/Api.Eventing.RabbitMq/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Eventing.RabbitMq/.kubernetes/deployment.yaml b/Api.Eventing.RabbitMq/.kubernetes/deployment.yaml
index c8e22634..5a30d851 100644
--- a/Api.Eventing.RabbitMq/.kubernetes/deployment.yaml
+++ b/Api.Eventing.RabbitMq/.kubernetes/deployment.yaml
@@ -38,16 +38,25 @@ spec:
- containerPort: 8080
imagePullPolicy: Always
env:
+ - name: Eventing__Credentials__Host
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: host
+ - name: Eventing__Credentials__Port
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: port
- name: Eventing__Credentials__Id
valueFrom:
secretKeyRef:
- name: rabbitmq-auth
+ name: rabbitmq-default-user
key: username
- envFrom:
- name: Eventing__Credentials__Secret
valueFrom:
secretKeyRef:
- name: rabbitmq-auth
+ name: rabbitmq-default-user
key: password
envFrom:
- configMapRef:
@@ -85,6 +94,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq.Models/Api.Eventing.RabbitMq.Models.csproj b/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq.Models/Api.Eventing.RabbitMq.Models.csproj
index 04328227..0a22c469 100644
--- a/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq.Models/Api.Eventing.RabbitMq.Models.csproj
+++ b/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq.Models/Api.Eventing.RabbitMq.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq/Dockerfile.Local b/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq/Dockerfile.Local
index e183367d..7efce886 100644
--- a/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq/Dockerfile.Local
+++ b/Api.Eventing.RabbitMq/Api.Eventing.RabbitMq/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Eventing.RabbitMq.dll"]
\ No newline at end of file
diff --git a/Api.Eventing.RabbitMq/Dockerfile b/Api.Eventing.RabbitMq/Dockerfile
index 4775d14f..487adf44 100644
--- a/Api.Eventing.RabbitMq/Dockerfile
+++ b/Api.Eventing.RabbitMq/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Eventing.RabbitMq/README.md b/Api.Eventing.RabbitMq/README.md
index 853d3e09..9b00625a 100644
--- a/Api.Eventing.RabbitMq/README.md
+++ b/Api.Eventing.RabbitMq/README.md
@@ -72,8 +72,8 @@ Configured the application `appsettings.json` with the necessary eventing setup.
"Heartbeat": 60,
"PrefetchCount": 50,
"Credentials": {
- "Id": "rabbitmq_user",
- "Secret": "password"
+ "Id": null,
+ "Secret": null
},
"HealthCheck": {
"UnhealthyStatus": "Unhealthy"
@@ -129,23 +129,32 @@ services:
## Kubernetes
Added the `rabbitmq` secret for password to the `deployment.yaml`.
-```json
+```yaml
spec:
template:
spec:
containers:
env:
+ - name: Eventing__Credentials__Host
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: host
+ - name: Eventing__Credentials__Port
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: port
- name: Eventing__Credentials__Id
valueFrom:
secretKeyRef:
- name: rabbitmq-auth
+ name: rabbitmq-default-user
key: username
- envFrom:
- name: Eventing__Credentials__Secret
valueFrom:
secretKeyRef:
- name: rabbitmq-auth
+ name: rabbitmq-default-user
key: password
```
-> ⚠️ The `rabbitmq` secret is created alongside the **[Nano Azure Kubernetes Eventing](https://github.com/Nano-Core/Nano.Azure.Kubernetes/tree/master/Nano.Azure.Kubernetes.RabbitMQ)**
+> ⚠️ The `rabbitmq` secret is created alongside the **[Nano.Azure.Kubernetes.RabbitMQ](https://github.com/Nano-Core/Nano.Azure.Kubernetes/tree/master/Nano.Azure.Kubernetes.RabbitMQ)**
diff --git a/Api.HealthChecks/.docker/docker-compose.yml b/Api.HealthChecks/.docker/docker-compose.yml
index dc34bde1..550a4254 100644
--- a/Api.HealthChecks/.docker/docker-compose.yml
+++ b/Api.HealthChecks/.docker/docker-compose.yml
@@ -5,9 +5,12 @@ services:
restart: on-failure
ports:
- 8080:8080
+ - 4443:4443
build:
context: ../Api.HealthChecks
dockerfile: "Dockerfile.Local"
+ volumes:
+ - ../:/root/.dotnet/https
networks:
- network
diff --git a/Api.HealthChecks/.github/workflows/build-and-deploy.yml b/Api.HealthChecks/.github/workflows/build-and-deploy.yml
index e09d6b24..67e919e4 100644
--- a/Api.HealthChecks/.github/workflows/build-and-deploy.yml
+++ b/Api.HealthChecks/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.HealthChecks
IMAGE_NAME: api.healthchecks
SERVICE_NAME: api-healthchecks
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DNS: ${{ vars.AZURE_RESOURCE_GROUP_DNS }}
+ AZURE_GROUP_LOGS: ${{ vars.AZURE_RESOURCE_GROUP_LOGS }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,22 +36,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
- AVAILABILITY_URI: ${{ github.ref == 'refs/heads/master' && format('https://{0}/healthz', secrets.PRODUCTION_HOST) || format('https://{0}/healthz', secrets.STAGING_HOST) }}
- AVAILABILITY_CHECK_FREQUENCY: 300
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,134 +61,78 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Add Availability Check
- id: add-availability-check
+ - name: Publish NuGet
shell: pwsh
run: |
- az extension add -n application-insights;
-
- $env:SERVICE_NAME_INSIGTHS = $env:SERVICE_NAME + "-insights";
- $env:APPLICATION_INSIGHT_ID = az monitor app-insights component show --query "[?contains(name, '$env:SERVICE_NAME_INSIGTHS')].[id]" -o tsv;
-
- if ([string]::IsNullOrEmpty($env:APPLICATION_INSIGHT_ID))
- {
- $env:WORKSPACE_ID = az monitor log-analytics workspace list --query "[?contains(name, 'log-analytics')].[id]" -o tsv;
-
- if (-not [string]::IsNullOrEmpty($env:WORKSPACE_ID))
- {
- $env:APPLICATION_INSIGHT_ID = az monitor app-insights component create `
- -a $env:SERVICE_NAME_INSIGTHS `
- -l $env:AZURE_LOCATION `
- -g $env:AZURE_GROUP `
- --workspace $env:WORKSPACE_ID `
- --query "[id]" -o tsv;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
- }
- };
-
- $env:SERVICE_NAME_AVAILABILITY = $env:SERVICE_NAME + '-availability-' + $env:ASPNETCORE_ENVIRONMENT.ToLower();
- $env:AVAILABILITY_ID = az monitor app-insights web-test list -g $env:AZURE_GROUP --query "[?contains(name, '$env:SERVICE_NAME_AVAILABILITY')].[id]" -o tsv;
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- if ([string]::IsNullOrEmpty($env:AVAILABILITY_ID))
- {
- $env:APPLICATION_INSIGHT_HIDDEN_LINK = 'hidden-link:' + $env:APPLICATION_INSIGHT_ID + '=Resource';
- az monitor app-insights web-test create `
- -n $env:SERVICE_NAME_AVAILABILITY `
- --defined-web-test-name $env:SERVICE_NAME_AVAILABILITY `
- -g $env:AZURE_GROUP `
- -l $env:AZURE_LOCATION `
- --kind multistep `
- --web-test-kind standard `
- --frequency $env:AVAILABILITY_CHECK_FREQUENCY `
- --enabled true `
- --retry-enabled true `
- --ssl-check true `
- --ssl-lifetime-check 30 `
- --http-verb GET `
- --request-url $env:AVAILABILITY_URI `
- --expected-status-code 200 `
- --content-validation content-match='\"status\":\"unhealthy\"' ignore-case=true pass-if-text-found=false `
- --tags $env:APPLICATION_INSIGHT_HIDDEN_LINK `
- --locations Id='us-ca-sjc-azr' `
- --locations Id='us-va-ash-azr' `
- --locations Id='emea-gb-db3-azr' `
- --locations Id='emea-nl-ams-azr' `
- --locations Id='apac-hk-hkn-azr';
- };
- if ($LastExitCode -ne 0)
+ if ($LastExitCode -ne 0)
{
throw "error";
- };
+ };
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ ./
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
- shell: pwsh
- run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
- name: Kubernetes Deploy
shell: pwsh
run: |
+ $zoneNames = az network dns zone list -g $env:AZURE_GROUP_DNS --query "[].name" -o json | ConvertFrom-Json
+
+ $env:ROUTE_HOST_NAMES = (
+ $zoneNames | ForEach-Object {
+ " - $env:SUB_DOMAIN_NAME.$_"
+ }
+ ) -join "`n"
+
+ $env:GATEWAY_NAME = kubectl get gateway -n $env:KUBERNETES_NAMESPACE -o jsonpath='{.items[0].metadata.name}'
+
Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
kubectl apply -f .kubernetes/service.tmp.yaml;
if ($LastExitCode -ne 0)
@@ -220,8 +161,111 @@ jobs:
throw "error";
};
+ Get-Content .kubernetes/httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-80.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-80.tmp.yaml;
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ }
+
+ Get-Content .kubernetes/httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-443.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-443.tmp.yaml;
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ }
+
+ - name: Add Availability Check
+ shell: pwsh
+ run: |
+ $env:AZURE_LOCATION = az monitor log-analytics workspace list -g $env:AZURE_GROUP_LOGS --query [0].location -o tsv;
+ $env:APPLICATION_INSIGHT_ID = az monitor app-insights component show -g $env:AZURE_GROUP_LOGS --query [0].id -o tsv;
+ $env:HIDDEN_LINK = 'hidden-link:' + $env:APPLICATION_INSIGHT_ID + '=Resource';
+
+ $zoneNames = az network dns zone list -g $env:AZURE_GROUP_DNS --query "[].name" -o json | ConvertFrom-Json
+
+ foreach ($zoneName in $zoneNames)
+ {
+ $env:WEB_TEST_NAME = $env:SERVICE_NAME + '-availability-' + $env:ASPNETCORE_ENVIRONMENT.ToLower() + '-' + $env:SUB_DOMAIN_NAME + '-' + ($zoneName.TrimEnd('.') -replace '\.', '-')
+
+ az monitor app-insights web-test show -g $env:AZURE_GROUP_LOGS -n $env:WEB_TEST_NAME --query id -o tsv 2>$null
+
+ if ($LastExitCode -ne 0)
+ {
+ az monitor app-insights web-test create `
+ -n $env:WEB_TEST_NAME `
+ --defined-web-test-name $env:WEB_TEST_NAME `
+ -g $env:AZURE_GROUP_LOGS `
+ -l $env:AZURE_LOCATION `
+ --kind ping `
+ --web-test-kind standard `
+ --frequency 300 `
+ --enabled true `
+ --retry-enabled true `
+ --ssl-check true `
+ --ssl-lifetime-check 30 `
+ --http-verb GET `
+ --request-url https://$env:SUB_DOMAIN_NAME.$zoneName/healthz `
+ --expected-status-code 200 `
+ --content-validation content-match='"status":"unhealthy"' ignore-case=true pass-if-text-found=false `
+ --tags $env:HIDDEN_LINK `
+ --locations Id='us-ca-sjc-azr' `
+ --locations Id='us-va-ash-azr' `
+ --locations Id='emea-gb-db3-azr' `
+ --locations Id='emea-nl-ams-azr' `
+ --locations Id='apac-hk-hkn-azr';
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ }
+ }
+
+ $env:WEB_TEST_ALERT_NAME = $env:WEB_TEST_NAME + "-alert";
+
+ az resource show -g $env:AZURE_GROUP_LOGS -n $env:WEB_TEST_ALERT_NAME --query id -o tsv 2>$null;
+
+ if ($LastExitCode -ne 0)
+ {
+ $env:WEB_TEST_ID = az monitor app-insights web-test show -g $env:AZURE_GROUP_LOGS -n $env:WEB_TEST_NAME --query id -o tsv;
+ $env:ACTION_GROUP_ID = az monitor action-group list -g $env:AZURE_GROUP_LOGS --query [0].id -o tsv;
+
+ $alertRuleProperties = @{
+ severity = 1
+ enabled = $true
+ scopes = @($env:WEB_TEST_ID, $env:APPLICATION_INSIGHT_ID)
+ evaluationFrequency = "PT1M"
+ windowSize = "PT5M"
+ criteria = @{
+ "odata.type" = "Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria"
+ webTestId = $env:WEB_TEST_ID
+ componentId = $env:APPLICATION_INSIGHT_ID
+ failedLocationCount = 2
+ }
+ actions = @(
+ @{ actionGroupId = $env:ACTION_GROUP_ID }
+ )
+ }
+
+ $json = $alertRuleProperties | ConvertTo-Json -Depth 10
+ [System.IO.File]::WriteAllText("$PWD/alert.json", $json, [System.Text.UTF8Encoding]::new($false))
+
+ az resource create `
+ -g $env:AZURE_GROUP_LOGS `
+ -n $env:WEB_TEST_ALERT_NAME `
+ -l global `
+ --resource-type "Microsoft.Insights/metricAlerts" `
+ -p '@alert.json';
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ }
+ }
+ }
+
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -229,6 +273,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.HealthChecks/.kubernetes/configmap.yaml b/Api.HealthChecks/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.HealthChecks/.kubernetes/configmap.yaml
+++ b/Api.HealthChecks/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.HealthChecks/.kubernetes/deployment.yaml b/Api.HealthChecks/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.HealthChecks/.kubernetes/deployment.yaml
+++ b/Api.HealthChecks/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.HealthChecks/.kubernetes/httproute-443.yaml b/Api.HealthChecks/.kubernetes/httproute-443.yaml
new file mode 100644
index 00000000..25060955
--- /dev/null
+++ b/Api.HealthChecks/.kubernetes/httproute-443.yaml
@@ -0,0 +1,18 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: %SERVICE_NAME%-route-443
+ namespace: %KUBERNETES_NAMESPACE%
+spec:
+ parentRefs:
+ - name: %GATEWAY_NAME%
+ hostnames:
+%ROUTE_HOST_NAMES%
+ rules:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ backendRefs:
+ - name: %SERVICE_NAME%
+ port: 8080
\ No newline at end of file
diff --git a/Api.HealthChecks/.kubernetes/httproute-80.yaml b/Api.HealthChecks/.kubernetes/httproute-80.yaml
new file mode 100644
index 00000000..e743bb46
--- /dev/null
+++ b/Api.HealthChecks/.kubernetes/httproute-80.yaml
@@ -0,0 +1,17 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: %SERVICE_NAME%-route-80
+ namespace: %KUBERNETES_NAMESPACE%
+spec:
+ parentRefs:
+ - name: %GATEWAY_NAME%
+ sectionName: http
+ hostnames:
+%ROUTE_HOST_NAMES%
+ rules:
+ - filters:
+ - type: RequestRedirect
+ requestRedirect:
+ scheme: https
+ statusCode: 301
\ No newline at end of file
diff --git a/Api.HealthChecks/Api.HealthChecks.Models/Api.HealthChecks.Models.csproj b/Api.HealthChecks/Api.HealthChecks.Models/Api.HealthChecks.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.HealthChecks/Api.HealthChecks.Models/Api.HealthChecks.Models.csproj
+++ b/Api.HealthChecks/Api.HealthChecks.Models/Api.HealthChecks.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.HealthChecks/Api.HealthChecks.sln b/Api.HealthChecks/Api.HealthChecks.sln
index 50d5122c..b0f55d32 100644
--- a/Api.HealthChecks/Api.HealthChecks.sln
+++ b/Api.HealthChecks/Api.HealthChecks.sln
@@ -10,6 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".solution", ".solution", "{
Dockerfile = Dockerfile
icon.png = icon.png
LICENSE = LICENSE
+ localhost.pfx = localhost.pfx
README.md = README.md
EndProjectSection
EndProject
@@ -22,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".kubernetes", ".kubernetes"
.kubernetes\autoscaler.yaml = .kubernetes\autoscaler.yaml
.kubernetes\configmap.yaml = .kubernetes\configmap.yaml
.kubernetes\deployment.yaml = .kubernetes\deployment.yaml
+ .kubernetes\httproute-443.yaml = .kubernetes\httproute-443.yaml
+ .kubernetes\httproute-80.yaml = .kubernetes\httproute-80.yaml
.kubernetes\service.yaml = .kubernetes\service.yaml
EndProjectSection
EndProject
diff --git a/Api.HealthChecks/Api.HealthChecks/Dockerfile.Local b/Api.HealthChecks/Api.HealthChecks/Dockerfile.Local
index 927b61e9..896d1208 100644
--- a/Api.HealthChecks/Api.HealthChecks/Dockerfile.Local
+++ b/Api.HealthChecks/Api.HealthChecks/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.HealthChecks.dll"]
\ No newline at end of file
diff --git a/Api.HealthChecks/Api.HealthChecks/appsettings.Development.json b/Api.HealthChecks/Api.HealthChecks/appsettings.Development.json
index 8593c62d..c298b7e5 100644
--- a/Api.HealthChecks/Api.HealthChecks/appsettings.Development.json
+++ b/Api.HealthChecks/Api.HealthChecks/appsettings.Development.json
@@ -1,2 +1,19 @@
{
+ "App": {
+ "Hosting": {
+ "Http": {
+ "UseHttpsRedirection": true
+ },
+ "Https": {
+ "Ports": [
+ 4443
+ ],
+ "Certificate": {
+ "Path": "/root/.dotnet/https/localhost.pfx",
+ "Password": "password"
+ },
+ "UseHttpsRequired": true
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Api.HealthChecks/Dockerfile b/Api.HealthChecks/Dockerfile
index 2e170ee4..2dfeea28 100644
--- a/Api.HealthChecks/Dockerfile
+++ b/Api.HealthChecks/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.HealthChecks/README.md b/Api.HealthChecks/README.md
index 18536976..0720ecca 100644
--- a/Api.HealthChecks/README.md
+++ b/Api.HealthChecks/README.md
@@ -18,7 +18,7 @@ Nano is referenced directly from source (not via NuGet packages) and is expected
* [GitHub Actions](#gitHub-actions)
## Summary
-This application builds on **[Api.Blank](https://github.com/Nano-Core/Nano.Lessons/tree/master/Api._Blank)** and adds a simple test controller
+This application builds on **[Api.Hosting.Https](https://github.com/Nano-Core/Nano.Lessons/tree/master/Api.Hosting.Https)** and adds a simple test controller
that inherits from the top-level Nano `BaseController`.
This example illustrates the use of Nano API health-checks.
@@ -46,79 +46,104 @@ There is no configuration for HealtCheck, the section has just been added to ena
## GitHub Actions
Optionally, you can configure an availability check in Azure using Application Insights to continuously monitor your application's health and responsiveness.
-> ⚠️ This requires the application to be exposed publicly from Kubernetes via an `ingress` configuration.
+> ⚠️ This requires the application to be exposed publicly from Kubernetes via an `httproute` configuration.
-Add the following environment variables.
+First, add the following environment variables.
```yaml
env:
- AVAILABILITY_URI: ${{ github.ref == 'refs/heads/master' && format('https://{0}/healthz', secrets.PRODUCTION_HOST) || format('https://{0}/healthz', secrets.STAGING_HOST) }}
- AVAILABILITY_CHECK_FREQUENCY: 300
+ AZURE_GROUP_LOGS: ${{ vars.AZURE_RESOURCE_GROUP_LOGS }}
```
-...and then add the `Add Availability Check` step to the action pipeline.
+And then the Availability Check step to the end of the pipeline.
```yaml
- - name: Add Availability Check
- id: add-availability-check
- shell: pwsh
- run: |
- sudo az extension add -n application-insights;
-
- $env:SERVICE_NAME_INSIGTHS = $env:SERVICE_NAME + "-insights";
- $env:APPLICATION_INSIGHT_ID = sudo az monitor app-insights component show --query "[?contains(name, '$env:SERVICE_NAME_INSIGTHS')].[id]" -o tsv;
-
- if ([string]::IsNullOrEmpty($env:APPLICATION_INSIGHT_ID))
- {
- $env:WORKSPACE_ID = sudo az monitor log-analytics workspace list --query "[?contains(name, 'log-analytics')].[id]" -o tsv;
-
- if (-not [string]::IsNullOrEmpty($env:WORKSPACE_ID))
- {
- $env:APPLICATION_INSIGHT_ID = sudo az monitor app-insights component create `
- -a $env:SERVICE_NAME_INSIGTHS `
- -l $env:AZURE_LOCATION `
- -g $env:AZURE_GROUP `
- --workspace $env:WORKSPACE_ID `
- --query "[id]" -o tsv;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
- }
- };
-
- $env:SERVICE_NAME_AVAILABILITY = $env:SERVICE_NAME + '-availability-' + $env:ASPNETCORE_ENVIRONMENT.ToLower();
- $env:AVAILABILITY_ID = sudo az monitor app-insights web-test list -g $env:AZURE_GROUP --query "[?contains(name, '$env:SERVICE_NAME_AVAILABILITY')].[id]" -o tsv;
-
- if ([string]::IsNullOrEmpty($env:AVAILABILITY_ID))
- {
- $env:APPLICATION_INSIGHT_HIDDEN_LINK = 'hidden-link:' + $env:APPLICATION_INSIGHT_ID + '=Resource';
- sudo az monitor app-insights web-test create `
- -n $env:SERVICE_NAME_AVAILABILITY `
- --defined-web-test-name $env:SERVICE_NAME_AVAILABILITY `
- -g $env:AZURE_GROUP `
- -l $env:AZURE_LOCATION `
- --kind multistep `
- --web-test-kind standard `
- --frequency $env:AVAILABILITY_CHECK_FREQUENCY `
- --enabled true `
- --retry-enabled true `
- --ssl-check true `
- --ssl-lifetime-check 30 `
- --http-verb GET `
- --request-url $env:AVAILABILITY_URI `
- --expected-status-code 200 `
- --content-validation content-match='\"status\":\"unhealthy\"' ignore-case=true pass-if-text-found=false `
- --tags $env:APPLICATION_INSIGHT_HIDDEN_LINK `
- --locations Id='us-ca-sjc-azr' `
- --locations Id='us-va-ash-azr' `
- --locations Id='emea-gb-db3-azr' `
- --locations Id='emea-nl-ams-azr' `
- --locations Id='apac-hk-hkn-azr';
- };
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+- name: Add Availability Check
+ shell: pwsh
+ run: |
+ $env:AZURE_LOCATION = az monitor log-analytics workspace list -g $env:AZURE_GROUP_LOGS --query [0].location -o tsv;
+ $env:APPLICATION_INSIGHT_ID = az monitor app-insights component show -g $env:AZURE_GROUP_LOGS --query [0].id -o tsv;
+ $env:HIDDEN_LINK = 'hidden-link:' + $env:APPLICATION_INSIGHT_ID + '=Resource';
+
+ $zoneNames = az network dns zone list -g $env:AZURE_GROUP_DNS --query "[].name" -o json | ConvertFrom-Json
+
+ foreach ($zoneName in $zoneNames)
+ {
+ $env:WEB_TEST_NAME = $env:SERVICE_NAME + '-availability-' + $env:ASPNETCORE_ENVIRONMENT.ToLower() + '-' + $env:SUB_DOMAIN_NAME + '-' + ($zoneName.TrimEnd('.') -replace '\.', '-')
+
+ az monitor app-insights web-test show -g $env:AZURE_GROUP_LOGS -n $env:WEB_TEST_NAME --query id -o tsv 2>$null
+
+ if ($LastExitCode -ne 0)
+ {
+ az monitor app-insights web-test create `
+ -n $env:WEB_TEST_NAME `
+ --defined-web-test-name $env:WEB_TEST_NAME `
+ -g $env:AZURE_GROUP_LOGS `
+ -l $env:AZURE_LOCATION `
+ --kind ping `
+ --web-test-kind standard `
+ --frequency 300 `
+ --enabled true `
+ --retry-enabled true `
+ --ssl-check true `
+ --ssl-lifetime-check 30 `
+ --http-verb GET `
+ --request-url https://$env:SUB_DOMAIN_NAME.$zoneName/healthz `
+ --expected-status-code 200 `
+ --content-validation content-match='"status":"unhealthy"' ignore-case=true pass-if-text-found=false `
+ --tags $env:HIDDEN_LINK `
+ --locations Id='us-ca-sjc-azr' `
+ --locations Id='us-va-ash-azr' `
+ --locations Id='emea-gb-db3-azr' `
+ --locations Id='emea-nl-ams-azr' `
+ --locations Id='apac-hk-hkn-azr';
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ }
+ }
+
+ $env:WEB_TEST_ALERT_NAME = $env:WEB_TEST_NAME + "-alert";
+
+ az resource show -g $env:AZURE_GROUP_LOGS -n $env:WEB_TEST_ALERT_NAME --query id -o tsv 2>$null;
+
+ if ($LastExitCode -ne 0)
+ {
+ $env:WEB_TEST_ID = az monitor app-insights web-test show -g $env:AZURE_GROUP_LOGS -n $env:WEB_TEST_NAME --query id -o tsv;
+ $env:ACTION_GROUP_ID = az monitor action-group list -g $env:AZURE_GROUP_LOGS --query [0].id -o tsv;
+
+ $alertRuleProperties = @{
+ severity = 1
+ enabled = $true
+ scopes = @($env:WEB_TEST_ID, $env:APPLICATION_INSIGHT_ID)
+ evaluationFrequency = "PT1M"
+ windowSize = "PT5M"
+ criteria = @{
+ "odata.type" = "Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria"
+ webTestId = $env:WEB_TEST_ID
+ componentId = $env:APPLICATION_INSIGHT_ID
+ failedLocationCount = 2
+ }
+ actions = @(
+ @{ actionGroupId = $env:ACTION_GROUP_ID }
+ )
+ }
+
+ $json = $alertRuleProperties | ConvertTo-Json -Depth 10
+ [System.IO.File]::WriteAllText("$PWD/alert.json", $json, [System.Text.UTF8Encoding]::new($false))
+
+ az resource create `
+ -g $env:AZURE_GROUP_LOGS `
+ -n $env:WEB_TEST_ALERT_NAME `
+ -l global `
+ --resource-type "Microsoft.Insights/metricAlerts" `
+ -p '@alert.json';
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ }
+ }
+ }
```
diff --git a/Api.HealthChecks/localhost.pfx b/Api.HealthChecks/localhost.pfx
new file mode 100644
index 00000000..22e513ca
Binary files /dev/null and b/Api.HealthChecks/localhost.pfx differ
diff --git a/Api.Hosting.Http/.github/workflows/build-and-deploy.yml b/Api.Hosting.Http/.github/workflows/build-and-deploy.yml
index 730be7cd..f1f9386e 100644
--- a/Api.Hosting.Http/.github/workflows/build-and-deploy.yml
+++ b/Api.Hosting.Http/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Hosting.Http
IMAGE_NAME: api.hosting.http
SERVICE_NAME: api-hosting-http
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Hosting.Http/.kubernetes/configmap.yaml b/Api.Hosting.Http/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Hosting.Http/.kubernetes/configmap.yaml
+++ b/Api.Hosting.Http/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Hosting.Http/.kubernetes/deployment.yaml b/Api.Hosting.Http/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Hosting.Http/.kubernetes/deployment.yaml
+++ b/Api.Hosting.Http/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Hosting.Http/Api.Hosting.Http.Models/Api.Hosting.Http.Models.csproj b/Api.Hosting.Http/Api.Hosting.Http.Models/Api.Hosting.Http.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Hosting.Http/Api.Hosting.Http.Models/Api.Hosting.Http.Models.csproj
+++ b/Api.Hosting.Http/Api.Hosting.Http.Models/Api.Hosting.Http.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Hosting.Http/Api.Hosting.Http/Dockerfile.Local b/Api.Hosting.Http/Api.Hosting.Http/Dockerfile.Local
index 272c1ffb..3a443213 100644
--- a/Api.Hosting.Http/Api.Hosting.Http/Dockerfile.Local
+++ b/Api.Hosting.Http/Api.Hosting.Http/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Hosting.Http.dll"]
\ No newline at end of file
diff --git a/Api.Hosting.Http/Dockerfile b/Api.Hosting.Http/Dockerfile
index 2d614ac6..b5601062 100644
--- a/Api.Hosting.Http/Dockerfile
+++ b/Api.Hosting.Http/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Hosting.Https/.github/workflows/build-and-deploy.yml b/Api.Hosting.Https/.github/workflows/build-and-deploy.yml
index 629d9c6f..d0b4ac6a 100644
--- a/Api.Hosting.Https/.github/workflows/build-and-deploy.yml
+++ b/Api.Hosting.Https/.github/workflows/build-and-deploy.yml
@@ -2,35 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Hosting.Https
IMAGE_NAME: api.hosting.https
SERVICE_NAME: api-hosting-https
SUB_DOMAIN_NAME: nano
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_GROUP_DNS: ${{ vars.AZURE_RESOURCE_GROUP_DNS }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,20 +36,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,68 +61,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -137,7 +131,7 @@ jobs:
}
) -join "`n"
- $env:GATEWAY_NAME = kubectl get gateway -n apps -o jsonpath='{.items[0].metadata.name}'
+ $env:GATEWAY_NAME = kubectl get gateway -n $env:KUBERNETES_NAMESPACE -o jsonpath='{.items[0].metadata.name}'
Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
kubectl apply -f .kubernetes/service.tmp.yaml;
@@ -167,22 +161,22 @@ jobs:
throw "error";
}
- Get-Content .kubernetes/grafana-httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/grafana-httproute-80.tmp.yaml;
- kubectl apply -f .kubernetes/grafana-httproute-80.tmp.yaml;
+ Get-Content .kubernetes/httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-80.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-80.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- Get-Content .kubernetes/grafana-httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/grafana-httproute-443.tmp.yaml;
- kubectl apply -f .kubernetes/grafana-httproute-443.tmp.yaml;
+ Get-Content .kubernetes/httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-443.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-443.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -190,6 +184,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Hosting.Https/.kubernetes/configmap.yaml b/Api.Hosting.Https/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Hosting.Https/.kubernetes/configmap.yaml
+++ b/Api.Hosting.Https/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Hosting.Https/.kubernetes/deployment.yaml b/Api.Hosting.Https/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Hosting.Https/.kubernetes/deployment.yaml
+++ b/Api.Hosting.Https/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Hosting.Https/.kubernetes/httproute-443.yaml b/Api.Hosting.Https/.kubernetes/httproute-443.yaml
index 65b97a51..25060955 100644
--- a/Api.Hosting.Https/.kubernetes/httproute-443.yaml
+++ b/Api.Hosting.Https/.kubernetes/httproute-443.yaml
@@ -1,7 +1,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
- name: %SERVICE_NAME%-route
+ name: %SERVICE_NAME%-route-443
namespace: %KUBERNETES_NAMESPACE%
spec:
parentRefs:
diff --git a/Api.Hosting.Https/.kubernetes/httproute-80.yaml b/Api.Hosting.Https/.kubernetes/httproute-80.yaml
index f29775aa..e743bb46 100644
--- a/Api.Hosting.Https/.kubernetes/httproute-80.yaml
+++ b/Api.Hosting.Https/.kubernetes/httproute-80.yaml
@@ -1,7 +1,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
- name: %APP_NAME%-route-80
+ name: %SERVICE_NAME%-route-80
namespace: %KUBERNETES_NAMESPACE%
spec:
parentRefs:
diff --git a/Api.Hosting.Https/Api.Hosting.Https.Models/Api.Hosting.Https.Models.csproj b/Api.Hosting.Https/Api.Hosting.Https.Models/Api.Hosting.Https.Models.csproj
index 7a4d41f3..5721d8ef 100644
--- a/Api.Hosting.Https/Api.Hosting.Https.Models/Api.Hosting.Https.Models.csproj
+++ b/Api.Hosting.Https/Api.Hosting.Https.Models/Api.Hosting.Https.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Hosting.Https/Api.Hosting.Https/Dockerfile.Local b/Api.Hosting.Https/Api.Hosting.Https/Dockerfile.Local
index e15900e2..c0b93077 100644
--- a/Api.Hosting.Https/Api.Hosting.Https/Dockerfile.Local
+++ b/Api.Hosting.Https/Api.Hosting.Https/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080 4443
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Hosting.Https.dll"]
\ No newline at end of file
diff --git a/Api.Hosting.Https/Api.Hosting.Https/appsettings.Development.json b/Api.Hosting.Https/Api.Hosting.Https/appsettings.Development.json
index 23bfb871..c298b7e5 100644
--- a/Api.Hosting.Https/Api.Hosting.Https/appsettings.Development.json
+++ b/Api.Hosting.Https/Api.Hosting.Https/appsettings.Development.json
@@ -1,7 +1,7 @@
{
"App": {
"Hosting": {
- "http": {
+ "Http": {
"UseHttpsRedirection": true
},
"Https": {
diff --git a/Api.Hosting.Https/Api.Hosting.Https/appsettings.json b/Api.Hosting.Https/Api.Hosting.Https/appsettings.json
index e8d9ff25..31aeb899 100644
--- a/Api.Hosting.Https/Api.Hosting.Https/appsettings.json
+++ b/Api.Hosting.Https/Api.Hosting.Https/appsettings.json
@@ -6,7 +6,8 @@
"Http": {
"Ports": [
8080
- ]
+ ],
+ "UseHttpsRedirection": false
}
}
}
diff --git a/Api.Hosting.Https/Dockerfile b/Api.Hosting.Https/Dockerfile
index ed3c969f..c001d061 100644
--- a/Api.Hosting.Https/Dockerfile
+++ b/Api.Hosting.Https/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Hosting.Https/README.md b/Api.Hosting.Https/README.md
index b9bf791d..37598f0e 100644
--- a/Api.Hosting.Https/README.md
+++ b/Api.Hosting.Https/README.md
@@ -43,6 +43,24 @@ HTTPS and the development certificate are only configured in `appsettings.Develo
in Kubernetes. Certificates are managed externally, and the service only needs to expose an HTTP port in `service.yaml` for mapping traffic through the ingress,
which serves HTTPS and forwards it to HTTP.
+The `appsettings.json` has this configuration.
+
+```json
+"App": {
+ "Hosting": {
+ "Root": "api",
+ "Http": {
+ "Ports": [
+ 8080
+ ],
+ "UseHttpsRedirection": false
+ }
+ }
+}
+```
+
+and the `appsettings.Development.json` this.
+
```json
"App": {
"Hosting": {
@@ -76,19 +94,72 @@ services:
```
## Kubernetes
-A `httproute.yaml` resource has been added to the `.kubernetes` folder.
+A `httproute-80.yaml` and `httproute-443.yaml` resource has been added.
-| File / Directory | Type | Description |
-| -------------------- | ------- | -------------------------------------------- |
-| `httproute.yaml` | `yaml` | The http route spec for Kubernetes Gateway. |
+```yaml
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: %SERVICE_NAME%-route-80
+ namespace: %KUBERNETES_NAMESPACE%
+spec:
+ parentRefs:
+ - name: %GATEWAY_NAME%
+ sectionName: http
+ hostnames:
+%ROUTE_HOST_NAMES%
+ rules:
+ - filters:
+ - type: RequestRedirect
+ requestRedirect:
+ scheme: https
+ statusCode: 301
+
+```
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: %SERVICE_NAME%-route-443
+ namespace: %KUBERNETES_NAMESPACE%
+spec:
+ parentRefs:
+ - name: %GATEWAY_NAME%
+ hostnames:
+%ROUTE_HOST_NAMES%
+ rules:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ backendRefs:
+ - name: %SERVICE_NAME%
+ port: 8080
+```
## GitHub Actions
-Deployment commands have been updated to apply the new Kubernetes `HTTPRoute` template.
+Add the following environment variables to the `buid-and-deply.yml`.
+
+```yaml
+env:
+ SUB_DOMAIN_NAME: papi
+ AZURE_GROUP_DNS: ${{ vars.AZURE_RESOURCE_GROUP_DNS }}
+```
+
+Additionally, during the Kubernetes deployment step, before any resources are applied, all DNS zones are iterated, and the hostname configured in the `httpRoutes` resource is updated to
+include the application's subdomain.
```powershell
-Get-Content .kubernetes/{resource-name}.yaml `
- | foreach { [Environment]::ExpandEnvironmentVariables($_) } `
- | Set-Content .kubernetes/{resource-name}.tmp.yaml;
+$zoneNames = az network dns zone list -g $env:AZURE_GROUP_DNS --query "[].name" -o json | ConvertFrom-Json
-sudo kubectl apply -f .kubernetes/{resource-name}.tmp.yaml;
+$env:ROUTE_HOST_NAMES = (
+ $zoneNames | ForEach-Object {
+ " - $env:SUB_DOMAIN_NAME.$_"
+ }
+) -join "`n"
+
+$env:GATEWAY_NAME = kubectl get gateway -n $env:KUBERNETES_NAMESPACE -o jsonpath='{.items[0].metadata.name}'
```
+
+The deployment commands have been updated to apply the new Kubernetes `HTTPRoute` templates.
diff --git a/Api.Hosting.MultipartLimits/.github/workflows/build-and-deploy.yml b/Api.Hosting.MultipartLimits/.github/workflows/build-and-deploy.yml
index 4ca38002..c6283627 100644
--- a/Api.Hosting.MultipartLimits/.github/workflows/build-and-deploy.yml
+++ b/Api.Hosting.MultipartLimits/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Hosting.MultipartLimits
IMAGE_NAME: api.hosting.multipartlimits
SERVICE_NAME: api-Hosting-multipartlimits
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Hosting.MultipartLimits/.kubernetes/configmap.yaml b/Api.Hosting.MultipartLimits/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Hosting.MultipartLimits/.kubernetes/configmap.yaml
+++ b/Api.Hosting.MultipartLimits/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Hosting.MultipartLimits/.kubernetes/deployment.yaml b/Api.Hosting.MultipartLimits/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Hosting.MultipartLimits/.kubernetes/deployment.yaml
+++ b/Api.Hosting.MultipartLimits/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits.Models/Api.Hosting.MultipartLimits.Models.csproj b/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits.Models/Api.Hosting.MultipartLimits.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits.Models/Api.Hosting.MultipartLimits.Models.csproj
+++ b/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits.Models/Api.Hosting.MultipartLimits.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits/Dockerfile.Local b/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits/Dockerfile.Local
index e80d58e4..81a4ac08 100644
--- a/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits/Dockerfile.Local
+++ b/Api.Hosting.MultipartLimits/Api.Hosting.MultipartLimits/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Hosting.MultipartLimits.dll"]
\ No newline at end of file
diff --git a/Api.Hosting.MultipartLimits/Dockerfile b/Api.Hosting.MultipartLimits/Dockerfile
index b205db82..8c3a1f9a 100644
--- a/Api.Hosting.MultipartLimits/Dockerfile
+++ b/Api.Hosting.MultipartLimits/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Localization/.github/workflows/build-and-deploy.yml b/Api.Localization/.github/workflows/build-and-deploy.yml
index 5e3244b5..4190f5e9 100644
--- a/Api.Localization/.github/workflows/build-and-deploy.yml
+++ b/Api.Localization/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Localization
IMAGE_NAME: api.localization
SERVICE_NAME: api-localization
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Localization/.kubernetes/configmap.yaml b/Api.Localization/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Localization/.kubernetes/configmap.yaml
+++ b/Api.Localization/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Localization/.kubernetes/deployment.yaml b/Api.Localization/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Localization/.kubernetes/deployment.yaml
+++ b/Api.Localization/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Localization/Api.Localization.Models/Api.Localization.Models.csproj b/Api.Localization/Api.Localization.Models/Api.Localization.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Localization/Api.Localization.Models/Api.Localization.Models.csproj
+++ b/Api.Localization/Api.Localization.Models/Api.Localization.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Localization/Api.Localization/Dockerfile.Local b/Api.Localization/Api.Localization/Dockerfile.Local
index 4cb9e786..9cdf2a5a 100644
--- a/Api.Localization/Api.Localization/Dockerfile.Local
+++ b/Api.Localization/Api.Localization/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Localization.dll"]
\ No newline at end of file
diff --git a/Api.Localization/Dockerfile b/Api.Localization/Dockerfile
index 14247453..8d9dd6a6 100644
--- a/Api.Localization/Dockerfile
+++ b/Api.Localization/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Logging.Log4Net/.github/workflows/build-and-deploy.yml b/Api.Logging.Log4Net/.github/workflows/build-and-deploy.yml
index 51e37842..01451c84 100644
--- a/Api.Logging.Log4Net/.github/workflows/build-and-deploy.yml
+++ b/Api.Logging.Log4Net/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Logging.Log4Net
IMAGE_NAME: api.logging.log4net
SERVICE_NAME: api-logging-log4net
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Logging.Log4Net/.kubernetes/configmap.yaml b/Api.Logging.Log4Net/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Logging.Log4Net/.kubernetes/configmap.yaml
+++ b/Api.Logging.Log4Net/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Logging.Log4Net/.kubernetes/deployment.yaml b/Api.Logging.Log4Net/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Logging.Log4Net/.kubernetes/deployment.yaml
+++ b/Api.Logging.Log4Net/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Logging.Log4Net/Api.Logging.Log4Net.Models/Api.Logging.Log4Net.Models.csproj b/Api.Logging.Log4Net/Api.Logging.Log4Net.Models/Api.Logging.Log4Net.Models.csproj
index 6d16235d..efa590a5 100644
--- a/Api.Logging.Log4Net/Api.Logging.Log4Net.Models/Api.Logging.Log4Net.Models.csproj
+++ b/Api.Logging.Log4Net/Api.Logging.Log4Net.Models/Api.Logging.Log4Net.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Logging.Log4Net/Api.Logging.Log4Net/Dockerfile.Local b/Api.Logging.Log4Net/Api.Logging.Log4Net/Dockerfile.Local
index 722f4503..9e7afe28 100644
--- a/Api.Logging.Log4Net/Api.Logging.Log4Net/Dockerfile.Local
+++ b/Api.Logging.Log4Net/Api.Logging.Log4Net/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Logging.Log4Net.dll"]
\ No newline at end of file
diff --git a/Api.Logging.Log4Net/Dockerfile b/Api.Logging.Log4Net/Dockerfile
index 8ba64365..13e88f32 100644
--- a/Api.Logging.Log4Net/Dockerfile
+++ b/Api.Logging.Log4Net/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Logging.Microsoft/.github/workflows/build-and-deploy.yml b/Api.Logging.Microsoft/.github/workflows/build-and-deploy.yml
index c4343328..239840d2 100644
--- a/Api.Logging.Microsoft/.github/workflows/build-and-deploy.yml
+++ b/Api.Logging.Microsoft/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Logging.Microsoft
IMAGE_NAME: api.logging.microsoft
SERVICE_NAME: api-logging-microsoft
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Logging.Microsoft/.kubernetes/configmap.yaml b/Api.Logging.Microsoft/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Logging.Microsoft/.kubernetes/configmap.yaml
+++ b/Api.Logging.Microsoft/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Logging.Microsoft/.kubernetes/deployment.yaml b/Api.Logging.Microsoft/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Logging.Microsoft/.kubernetes/deployment.yaml
+++ b/Api.Logging.Microsoft/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Logging.Microsoft/Api.Logging.Microsoft.Models/Api.Logging.Microsoft.Models.csproj b/Api.Logging.Microsoft/Api.Logging.Microsoft.Models/Api.Logging.Microsoft.Models.csproj
index a284b2dc..2bf37abf 100644
--- a/Api.Logging.Microsoft/Api.Logging.Microsoft.Models/Api.Logging.Microsoft.Models.csproj
+++ b/Api.Logging.Microsoft/Api.Logging.Microsoft.Models/Api.Logging.Microsoft.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Logging.Microsoft/Api.Logging.Microsoft/Dockerfile.Local b/Api.Logging.Microsoft/Api.Logging.Microsoft/Dockerfile.Local
index adaac8c3..db46c6db 100644
--- a/Api.Logging.Microsoft/Api.Logging.Microsoft/Dockerfile.Local
+++ b/Api.Logging.Microsoft/Api.Logging.Microsoft/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Logging.Microsoft.dll"]
\ No newline at end of file
diff --git a/Api.Logging.Microsoft/Dockerfile b/Api.Logging.Microsoft/Dockerfile
index d77a0004..efecbaea 100644
--- a/Api.Logging.Microsoft/Dockerfile
+++ b/Api.Logging.Microsoft/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Logging.NLog/.github/workflows/build-and-deploy.yml b/Api.Logging.NLog/.github/workflows/build-and-deploy.yml
index 16faef4c..887a4cdc 100644
--- a/Api.Logging.NLog/.github/workflows/build-and-deploy.yml
+++ b/Api.Logging.NLog/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Logging.NLog
IMAGE_NAME: api.logging.nlog
SERVICE_NAME: api-logging-nlog
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Logging.NLog/.kubernetes/configmap.yaml b/Api.Logging.NLog/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Logging.NLog/.kubernetes/configmap.yaml
+++ b/Api.Logging.NLog/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Logging.NLog/.kubernetes/deployment.yaml b/Api.Logging.NLog/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Logging.NLog/.kubernetes/deployment.yaml
+++ b/Api.Logging.NLog/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Logging.NLog/Api.Logging.NLog.Models/Api.Logging.NLog.Models.csproj b/Api.Logging.NLog/Api.Logging.NLog.Models/Api.Logging.NLog.Models.csproj
index 8989e105..6a72671e 100644
--- a/Api.Logging.NLog/Api.Logging.NLog.Models/Api.Logging.NLog.Models.csproj
+++ b/Api.Logging.NLog/Api.Logging.NLog.Models/Api.Logging.NLog.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Logging.NLog/Api.Logging.NLog/Dockerfile.Local b/Api.Logging.NLog/Api.Logging.NLog/Dockerfile.Local
index e47db8d4..189a4a79 100644
--- a/Api.Logging.NLog/Api.Logging.NLog/Dockerfile.Local
+++ b/Api.Logging.NLog/Api.Logging.NLog/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Logging.NLog.dll"]
\ No newline at end of file
diff --git a/Api.Logging.NLog/Dockerfile b/Api.Logging.NLog/Dockerfile
index f7f28f9d..7a27e439 100644
--- a/Api.Logging.NLog/Dockerfile
+++ b/Api.Logging.NLog/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Logging.Serilog/.github/workflows/build-and-deploy.yml b/Api.Logging.Serilog/.github/workflows/build-and-deploy.yml
index c26ccdfb..bb2d2eb3 100644
--- a/Api.Logging.Serilog/.github/workflows/build-and-deploy.yml
+++ b/Api.Logging.Serilog/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Logging.Serilog
IMAGE_NAME: api.logging.serilog
SERVICE_NAME: api-logging-serilog
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Logging.Serilog/.kubernetes/configmap.yaml b/Api.Logging.Serilog/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Logging.Serilog/.kubernetes/configmap.yaml
+++ b/Api.Logging.Serilog/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Logging.Serilog/.kubernetes/deployment.yaml b/Api.Logging.Serilog/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Logging.Serilog/.kubernetes/deployment.yaml
+++ b/Api.Logging.Serilog/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Logging.Serilog/Api.Logging.Serilog.Models/Api.Logging.Serilog.Models.csproj b/Api.Logging.Serilog/Api.Logging.Serilog.Models/Api.Logging.Serilog.Models.csproj
index d1fa3771..ded626a7 100644
--- a/Api.Logging.Serilog/Api.Logging.Serilog.Models/Api.Logging.Serilog.Models.csproj
+++ b/Api.Logging.Serilog/Api.Logging.Serilog.Models/Api.Logging.Serilog.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Logging.Serilog/Api.Logging.Serilog/Dockerfile.Local b/Api.Logging.Serilog/Api.Logging.Serilog/Dockerfile.Local
index 006fb412..8e77303a 100644
--- a/Api.Logging.Serilog/Api.Logging.Serilog/Dockerfile.Local
+++ b/Api.Logging.Serilog/Api.Logging.Serilog/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Logging.Serilog.dll"]
\ No newline at end of file
diff --git a/Api.Logging.Serilog/Dockerfile b/Api.Logging.Serilog/Dockerfile
index e211ed1c..f77d36b0 100644
--- a/Api.Logging.Serilog/Dockerfile
+++ b/Api.Logging.Serilog/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.MultipartJson/.github/workflows/build-and-deploy.yml b/Api.MultipartJson/.github/workflows/build-and-deploy.yml
index 8f3918cf..30954793 100644
--- a/Api.MultipartJson/.github/workflows/build-and-deploy.yml
+++ b/Api.MultipartJson/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.MultipartJson
IMAGE_NAME: api.multipartjson
SERVICE_NAME: api-multipartjson
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.MultipartJson/.kubernetes/configmap.yaml b/Api.MultipartJson/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.MultipartJson/.kubernetes/configmap.yaml
+++ b/Api.MultipartJson/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.MultipartJson/.kubernetes/deployment.yaml b/Api.MultipartJson/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.MultipartJson/.kubernetes/deployment.yaml
+++ b/Api.MultipartJson/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.MultipartJson/Api.MultipartJson.Models/Api.MultipartJson.Models.csproj b/Api.MultipartJson/Api.MultipartJson.Models/Api.MultipartJson.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.MultipartJson/Api.MultipartJson.Models/Api.MultipartJson.Models.csproj
+++ b/Api.MultipartJson/Api.MultipartJson.Models/Api.MultipartJson.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.MultipartJson/Api.MultipartJson/Dockerfile.Local b/Api.MultipartJson/Api.MultipartJson/Dockerfile.Local
index 8d1d3884..84d21494 100644
--- a/Api.MultipartJson/Api.MultipartJson/Dockerfile.Local
+++ b/Api.MultipartJson/Api.MultipartJson/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.MultipartJson.dll"]
\ No newline at end of file
diff --git a/Api.MultipartJson/Dockerfile b/Api.MultipartJson/Dockerfile
index efb0b01a..17fae898 100644
--- a/Api.MultipartJson/Dockerfile
+++ b/Api.MultipartJson/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.ContentSecurityPolicy/.github/workflows/build-and-deploy.yml
index c97c19fa..a854db52 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/.github/workflows/build-and-deploy.yml
@@ -2,35 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.ContentSecurityPolicy
IMAGE_NAME: api.policyheaders.contentsecuritypolicy
SERVICE_NAME: api-policyheaders-contentsecuritypolicy
SUB_DOMAIN_NAME: nano
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_DNS: ${{ vars.AZURE_RESOURCE_GROUP_DNS }}
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,20 +36,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,68 +61,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -137,52 +131,52 @@ jobs:
}
) -join "`n"
- $env:GATEWAY_NAME = kubectl get gateway -n apps -o jsonpath='{.items[0].metadata.name}'
+ $env:GATEWAY_NAME = kubectl get gateway -n $env:KUBERNETES_NAMESPACE -o jsonpath='{.items[0].metadata.name}'
Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
- kubectl apply -f service.tmp.yaml;
+ kubectl apply -f .kubernetes/service.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
Get-Content .kubernetes/configmap.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/configmap.tmp.yaml;
- kubectl apply -f configmap.tmp.yaml;
+ kubectl apply -f .kubernetes/configmap.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
Get-Content .kubernetes/deployment.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/deployment.tmp.yaml;
- kubectl apply -f deployment.tmp.yaml;
+ kubectl apply -f .kubernetes/deployment.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
Get-Content .kubernetes/autoscaler.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/autoscaler.tmp.yaml;
- kubectl apply -f autoscaler.tmp.yaml;
+ kubectl apply -f .kubernetes/autoscaler.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- Get-Content .kubernetes/grafana-httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/grafana-httproute-80.tmp.yaml;
- kubectl apply -f .kubernetes/grafana-httproute-80.tmp.yaml;
+ Get-Content .kubernetes/httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-80.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-80.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- Get-Content .kubernetes/grafana-httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/grafana-httproute-443.tmp.yaml;
- kubectl apply -f .kubernetes/grafana-httproute-443.tmp.yaml;
+ Get-Content .kubernetes/httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-443.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-443.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -190,6 +184,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/configmap.yaml b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/deployment.yaml b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-443.yaml b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-443.yaml
index 65b97a51..25060955 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-443.yaml
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-443.yaml
@@ -1,7 +1,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
- name: %SERVICE_NAME%-route
+ name: %SERVICE_NAME%-route-443
namespace: %KUBERNETES_NAMESPACE%
spec:
parentRefs:
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-80.yaml b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-80.yaml
index f29775aa..e743bb46 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-80.yaml
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/.kubernetes/httproute-80.yaml
@@ -1,7 +1,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
- name: %APP_NAME%-route-80
+ name: %SERVICE_NAME%-route-80
namespace: %KUBERNETES_NAMESPACE%
spec:
parentRefs:
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy.Models/Api.PolicyHeaders.ContentSecurityPolicy.Models.csproj b/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy.Models/Api.PolicyHeaders.ContentSecurityPolicy.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy.Models/Api.PolicyHeaders.ContentSecurityPolicy.Models.csproj
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy.Models/Api.PolicyHeaders.ContentSecurityPolicy.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile.Local b/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile.Local
index c6f98fe9..b9640a76 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile.Local
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080 4443
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.ContentSecurityPolicy.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/appsettings.Development.json b/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/appsettings.Development.json
index 23bfb871..c298b7e5 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/appsettings.Development.json
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/Api.PolicyHeaders.ContentSecurityPolicy/appsettings.Development.json
@@ -1,7 +1,7 @@
{
"App": {
"Hosting": {
- "http": {
+ "Http": {
"UseHttpsRedirection": true
},
"Https": {
diff --git a/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile b/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile
index 0bcd6f21..72e4073d 100644
--- a/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile
+++ b/Api.PolicyHeaders.ContentSecurityPolicy/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.ContentTypeOptions/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.ContentTypeOptions/.github/workflows/build-and-deploy.yml
index 4010720a..b60f0d24 100644
--- a/Api.PolicyHeaders.ContentTypeOptions/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.ContentTypeOptions/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.ContentTypeOptions
IMAGE_NAME: api.policyheaders.contenttypeoptions
SERVICE_NAME: api-policyheaders-contenttypeoptions
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/configmap.yaml b/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/deployment.yaml b/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.ContentTypeOptions/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions.Models/Api.PolicyHeaders.ContentTypeOptions.Models.csproj b/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions.Models/Api.PolicyHeaders.ContentTypeOptions.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions.Models/Api.PolicyHeaders.ContentTypeOptions.Models.csproj
+++ b/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions.Models/Api.PolicyHeaders.ContentTypeOptions.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions/Dockerfile.Local b/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions/Dockerfile.Local
index c7050317..7e1bd286 100644
--- a/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions/Dockerfile.Local
+++ b/Api.PolicyHeaders.ContentTypeOptions/Api.PolicyHeaders.ContentTypeOptions/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.ContentTypeOptions.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.ContentTypeOptions/Dockerfile b/Api.PolicyHeaders.ContentTypeOptions/Dockerfile
index fddba199..40f7676f 100644
--- a/Api.PolicyHeaders.ContentTypeOptions/Dockerfile
+++ b/Api.PolicyHeaders.ContentTypeOptions/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.Cors/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.Cors/.github/workflows/build-and-deploy.yml
index e53037ec..d1184302 100644
--- a/Api.PolicyHeaders.Cors/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.Cors/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.Cors
IMAGE_NAME: api.policyheaders.cors
SERVICE_NAME: api-policyheaders-cors
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,20 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+ CORS_ALLOWED_ORIGIN_0: web.domain.com
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +60,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +151,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +159,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.Cors/.kubernetes/configmap.yaml b/Api.PolicyHeaders.Cors/.kubernetes/configmap.yaml
index 3977c0ee..2067fb4a 100644
--- a/Api.PolicyHeaders.Cors/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.Cors/.kubernetes/configmap.yaml
@@ -1,8 +1,9 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
namespace: %KUBERNETES_NAMESPACE%
data:
App__Version: %VERSION%
+ App__HttpPolicyHeaders__Cors__AllowedOrigins__0: %CORS_ALLOWED_ORIGIN_0%
ASPNETCORE_ENVIRONMENT: %ASPNETCORE_ENVIRONMENT%
diff --git a/Api.PolicyHeaders.Cors/.kubernetes/deployment.yaml b/Api.PolicyHeaders.Cors/.kubernetes/deployment.yaml
index 02882c56..00eb67cf 100644
--- a/Api.PolicyHeaders.Cors/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.Cors/.kubernetes/deployment.yaml
@@ -73,6 +73,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors.Models/Api.PolicyHeaders.Cors.Models.csproj b/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors.Models/Api.PolicyHeaders.Cors.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors.Models/Api.PolicyHeaders.Cors.Models.csproj
+++ b/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors.Models/Api.PolicyHeaders.Cors.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors/Dockerfile.Local b/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors/Dockerfile.Local
index 27de0430..97f391eb 100644
--- a/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors/Dockerfile.Local
+++ b/Api.PolicyHeaders.Cors/Api.PolicyHeaders.Cors/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.Cors.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.Cors/Dockerfile b/Api.PolicyHeaders.Cors/Dockerfile
index 1c4803ef..bb8e8846 100644
--- a/Api.PolicyHeaders.Cors/Dockerfile
+++ b/Api.PolicyHeaders.Cors/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.ForwardedHeaders/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.ForwardedHeaders/.github/workflows/build-and-deploy.yml
index 2d9f7da3..6c3e09af 100644
--- a/Api.PolicyHeaders.ForwardedHeaders/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.ForwardedHeaders/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.ForwardedHeaders
IMAGE_NAME: api.policyheaders.forwardedheaders
SERVICE_NAME: api-policyheaders-forwardedheaders
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/configmap.yaml b/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/deployment.yaml b/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.ForwardedHeaders/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders.Models/Api.PolicyHeaders.ForwardedHeaders.Models.csproj b/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders.Models/Api.PolicyHeaders.ForwardedHeaders.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders.Models/Api.PolicyHeaders.ForwardedHeaders.Models.csproj
+++ b/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders.Models/Api.PolicyHeaders.ForwardedHeaders.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders/Dockerfile.Local b/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders/Dockerfile.Local
index dcca3656..0d524c40 100644
--- a/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders/Dockerfile.Local
+++ b/Api.PolicyHeaders.ForwardedHeaders/Api.PolicyHeaders.ForwardedHeaders/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.ForwardedHeaders.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.ForwardedHeaders/Dockerfile b/Api.PolicyHeaders.ForwardedHeaders/Dockerfile
index 2efeaed7..93f98ec7 100644
--- a/Api.PolicyHeaders.ForwardedHeaders/Dockerfile
+++ b/Api.PolicyHeaders.ForwardedHeaders/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.FrameOptions/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.FrameOptions/.github/workflows/build-and-deploy.yml
index 504d5a7e..d7656d46 100644
--- a/Api.PolicyHeaders.FrameOptions/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.FrameOptions/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.FrameOptions
IMAGE_NAME: api.policyheaders.frameoptions
SERVICE_NAME: api-policyheaders-frameoptions
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.FrameOptions/.kubernetes/configmap.yaml b/Api.PolicyHeaders.FrameOptions/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.FrameOptions/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.FrameOptions/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.FrameOptions/.kubernetes/deployment.yaml b/Api.PolicyHeaders.FrameOptions/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.FrameOptions/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.FrameOptions/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions.Models/Api.PolicyHeaders.FrameOptions.Models.csproj b/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions.Models/Api.PolicyHeaders.FrameOptions.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions.Models/Api.PolicyHeaders.FrameOptions.Models.csproj
+++ b/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions.Models/Api.PolicyHeaders.FrameOptions.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions/Dockerfile.Local b/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions/Dockerfile.Local
index bac6d4bb..f96b4e8e 100644
--- a/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions/Dockerfile.Local
+++ b/Api.PolicyHeaders.FrameOptions/Api.PolicyHeaders.FrameOptions/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.FrameOptions.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.FrameOptions/Dockerfile b/Api.PolicyHeaders.FrameOptions/Dockerfile
index dae0c7d9..b77e2d56 100644
--- a/Api.PolicyHeaders.FrameOptions/Dockerfile
+++ b/Api.PolicyHeaders.FrameOptions/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.Hsts/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.Hsts/.github/workflows/build-and-deploy.yml
index 2a01df3e..527d003a 100644
--- a/Api.PolicyHeaders.Hsts/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.Hsts/.github/workflows/build-and-deploy.yml
@@ -2,35 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.Hsts
IMAGE_NAME: api.policyheaders.hsts
SERVICE_NAME: api-policyheaders-hsts
SUB_DOMAIN_NAME: nano
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_GROUP_DNS: ${{ vars.AZURE_RESOURCE_GROUP_DNS }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -38,20 +36,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -64,68 +61,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -137,52 +131,52 @@ jobs:
}
) -join "`n"
- $env:GATEWAY_NAME = kubectl get gateway -n apps -o jsonpath='{.items[0].metadata.name}'
+ $env:GATEWAY_NAME = kubectl get gateway -n $env:KUBERNETES_NAMESPACE -o jsonpath='{.items[0].metadata.name}'
Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
- kubectl apply -f service.tmp.yaml;
+ kubectl apply -f .kubernetes/service.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
Get-Content .kubernetes/configmap.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/configmap.tmp.yaml;
- kubectl apply -f configmap.tmp.yaml;
+ kubectl apply -f .kubernetes/configmap.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
Get-Content .kubernetes/deployment.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/deployment.tmp.yaml;
- kubectl apply -f deployment.tmp.yaml;
+ kubectl apply -f .kubernetes/deployment.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
Get-Content .kubernetes/autoscaler.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/autoscaler.tmp.yaml;
- kubectl apply -f autoscaler.tmp.yaml;
+ kubectl apply -f .kubernetes/autoscaler.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- Get-Content .kubernetes/grafana-httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/grafana-httproute-80.tmp.yaml;
- kubectl apply -f .kubernetes/grafana-httproute-80.tmp.yaml;
+ Get-Content .kubernetes/httproute-80.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-80.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-80.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- Get-Content .kubernetes/grafana-httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/grafana-httproute-443.tmp.yaml;
- kubectl apply -f .kubernetes/grafana-httproute-443.tmp.yaml;
+ Get-Content .kubernetes/httproute-443.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/httproute-443.tmp.yaml;
+ kubectl apply -f .kubernetes/httproute-443.tmp.yaml;
if ($LastExitCode -ne 0)
{
throw "error";
}
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -190,6 +184,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.Hsts/.kubernetes/configmap.yaml b/Api.PolicyHeaders.Hsts/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.Hsts/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.Hsts/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.Hsts/.kubernetes/deployment.yaml b/Api.PolicyHeaders.Hsts/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.Hsts/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.Hsts/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.Hsts/.kubernetes/httproute-443.yaml b/Api.PolicyHeaders.Hsts/.kubernetes/httproute-443.yaml
index 65b97a51..25060955 100644
--- a/Api.PolicyHeaders.Hsts/.kubernetes/httproute-443.yaml
+++ b/Api.PolicyHeaders.Hsts/.kubernetes/httproute-443.yaml
@@ -1,7 +1,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
- name: %SERVICE_NAME%-route
+ name: %SERVICE_NAME%-route-443
namespace: %KUBERNETES_NAMESPACE%
spec:
parentRefs:
diff --git a/Api.PolicyHeaders.Hsts/.kubernetes/httproute-80.yaml b/Api.PolicyHeaders.Hsts/.kubernetes/httproute-80.yaml
index f29775aa..e743bb46 100644
--- a/Api.PolicyHeaders.Hsts/.kubernetes/httproute-80.yaml
+++ b/Api.PolicyHeaders.Hsts/.kubernetes/httproute-80.yaml
@@ -1,7 +1,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
- name: %APP_NAME%-route-80
+ name: %SERVICE_NAME%-route-80
namespace: %KUBERNETES_NAMESPACE%
spec:
parentRefs:
diff --git a/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts.Models/Api.PolicyHeaders.Hsts.Models.csproj b/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts.Models/Api.PolicyHeaders.Hsts.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts.Models/Api.PolicyHeaders.Hsts.Models.csproj
+++ b/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts.Models/Api.PolicyHeaders.Hsts.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts/Dockerfile.Local b/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts/Dockerfile.Local
index 86fa8383..800bceb7 100644
--- a/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts/Dockerfile.Local
+++ b/Api.PolicyHeaders.Hsts/Api.PolicyHeaders.Hsts/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080 4443
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.Hsts.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.Hsts/Dockerfile b/Api.PolicyHeaders.Hsts/Dockerfile
index 477de8f6..ae132a12 100644
--- a/Api.PolicyHeaders.Hsts/Dockerfile
+++ b/Api.PolicyHeaders.Hsts/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.ReferrerPolicy/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.ReferrerPolicy/.github/workflows/build-and-deploy.yml
index 9ae23278..2889f518 100644
--- a/Api.PolicyHeaders.ReferrerPolicy/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.ReferrerPolicy/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.ReferrerPolicy
IMAGE_NAME: api.policyheaders.referrerpolicy
SERVICE_NAME: api-policyheaders-referrerpolicy
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/configmap.yaml b/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/deployment.yaml b/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.ReferrerPolicy/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy.Models/Api.PolicyHeaders.ReferrerPolicy.Models.csproj b/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy.Models/Api.PolicyHeaders.ReferrerPolicy.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy.Models/Api.PolicyHeaders.ReferrerPolicy.Models.csproj
+++ b/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy.Models/Api.PolicyHeaders.ReferrerPolicy.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy/Dockerfile.Local b/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy/Dockerfile.Local
index fc184f16..e33b2091 100644
--- a/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy/Dockerfile.Local
+++ b/Api.PolicyHeaders.ReferrerPolicy/Api.PolicyHeaders.ReferrerPolicy/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.ReferrerPolicy.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.ReferrerPolicy/Dockerfile b/Api.PolicyHeaders.ReferrerPolicy/Dockerfile
index 48e82726..1337ee8f 100644
--- a/Api.PolicyHeaders.ReferrerPolicy/Dockerfile
+++ b/Api.PolicyHeaders.ReferrerPolicy/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.Robots/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.Robots/.github/workflows/build-and-deploy.yml
index 3699c699..b24e091d 100644
--- a/Api.PolicyHeaders.Robots/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.Robots/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.Robots
IMAGE_NAME: api.policyheaders.robots
SERVICE_NAME: api-policyheaders-robots
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.Robots/.kubernetes/configmap.yaml b/Api.PolicyHeaders.Robots/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.Robots/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.Robots/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.Robots/.kubernetes/deployment.yaml b/Api.PolicyHeaders.Robots/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.PolicyHeaders.Robots/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.Robots/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots.Models/Api.PolicyHeaders.Robots.Models.csproj b/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots.Models/Api.PolicyHeaders.Robots.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots.Models/Api.PolicyHeaders.Robots.Models.csproj
+++ b/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots.Models/Api.PolicyHeaders.Robots.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots/Dockerfile.Local b/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots/Dockerfile.Local
index 8a943b01..19cdffd3 100644
--- a/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots/Dockerfile.Local
+++ b/Api.PolicyHeaders.Robots/Api.PolicyHeaders.Robots/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.Robots.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.Robots/Dockerfile b/Api.PolicyHeaders.Robots/Dockerfile
index f349f074..f7203acb 100644
--- a/Api.PolicyHeaders.Robots/Dockerfile
+++ b/Api.PolicyHeaders.Robots/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.PolicyHeaders.XssProtection/.github/workflows/build-and-deploy.yml b/Api.PolicyHeaders.XssProtection/.github/workflows/build-and-deploy.yml
index 8673f1f9..af7750de 100644
--- a/Api.PolicyHeaders.XssProtection/.github/workflows/build-and-deploy.yml
+++ b/Api.PolicyHeaders.XssProtection/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.PolicyHeaders.XssProtection
IMAGE_NAME: api.policyheaders.xssprotection
SERVICE_NAME: api-policyheaders-xssprotection
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.PolicyHeaders.XssProtection/.kubernetes/configmap.yaml b/Api.PolicyHeaders.XssProtection/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.PolicyHeaders.XssProtection/.kubernetes/configmap.yaml
+++ b/Api.PolicyHeaders.XssProtection/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.PolicyHeaders.XssProtection/.kubernetes/deployment.yaml b/Api.PolicyHeaders.XssProtection/.kubernetes/deployment.yaml
index 02882c56..00eb67cf 100644
--- a/Api.PolicyHeaders.XssProtection/.kubernetes/deployment.yaml
+++ b/Api.PolicyHeaders.XssProtection/.kubernetes/deployment.yaml
@@ -73,6 +73,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection.Models/Api.PolicyHeaders.XssProtection.Models.csproj b/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection.Models/Api.PolicyHeaders.XssProtection.Models.csproj
index 890be2f1..9b70eeab 100644
--- a/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection.Models/Api.PolicyHeaders.XssProtection.Models.csproj
+++ b/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection.Models/Api.PolicyHeaders.XssProtection.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection/Dockerfile.Local b/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection/Dockerfile.Local
index 0564fe65..59bc4b13 100644
--- a/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection/Dockerfile.Local
+++ b/Api.PolicyHeaders.XssProtection/Api.PolicyHeaders.XssProtection/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.PolicyHeaders.XssProtection.dll"]
\ No newline at end of file
diff --git a/Api.PolicyHeaders.XssProtection/Dockerfile b/Api.PolicyHeaders.XssProtection/Dockerfile
index b9e1371d..605a1811 100644
--- a/Api.PolicyHeaders.XssProtection/Dockerfile
+++ b/Api.PolicyHeaders.XssProtection/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.RequestTracing/.github/workflows/build-and-deploy.yml b/Api.RequestTracing/.github/workflows/build-and-deploy.yml
index 0f92a439..ef29ed2f 100644
--- a/Api.RequestTracing/.github/workflows/build-and-deploy.yml
+++ b/Api.RequestTracing/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.RequestTracing
IMAGE_NAME: api.requesttracing
SERVICE_NAME: api-requesttracing
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.RequestTracing/.kubernetes/configmap.yaml b/Api.RequestTracing/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.RequestTracing/.kubernetes/configmap.yaml
+++ b/Api.RequestTracing/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.RequestTracing/.kubernetes/deployment.yaml b/Api.RequestTracing/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.RequestTracing/.kubernetes/deployment.yaml
+++ b/Api.RequestTracing/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.RequestTracing/Api.RequestTracing.Models/Api.RequestTracing.Models.csproj b/Api.RequestTracing/Api.RequestTracing.Models/Api.RequestTracing.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.RequestTracing/Api.RequestTracing.Models/Api.RequestTracing.Models.csproj
+++ b/Api.RequestTracing/Api.RequestTracing.Models/Api.RequestTracing.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.RequestTracing/Api.RequestTracing/Dockerfile.Local b/Api.RequestTracing/Api.RequestTracing/Dockerfile.Local
index 87cc5040..85a3edd9 100644
--- a/Api.RequestTracing/Api.RequestTracing/Dockerfile.Local
+++ b/Api.RequestTracing/Api.RequestTracing/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.RequestTracing.dll"]
\ No newline at end of file
diff --git a/Api.RequestTracing/Dockerfile b/Api.RequestTracing/Dockerfile
index 316aafa3..30be91b7 100644
--- a/Api.RequestTracing/Dockerfile
+++ b/Api.RequestTracing/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ResponseCache/.github/workflows/build-and-deploy.yml b/Api.ResponseCache/.github/workflows/build-and-deploy.yml
index b01ba103..7b0df2ac 100644
--- a/Api.ResponseCache/.github/workflows/build-and-deploy.yml
+++ b/Api.ResponseCache/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ResponseCache
IMAGE_NAME: api.responsecache
SERVICE_NAME: api-responsecache
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ResponseCache/.kubernetes/configmap.yaml b/Api.ResponseCache/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ResponseCache/.kubernetes/configmap.yaml
+++ b/Api.ResponseCache/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ResponseCache/.kubernetes/deployment.yaml b/Api.ResponseCache/.kubernetes/deployment.yaml
index 02882c56..00eb67cf 100644
--- a/Api.ResponseCache/.kubernetes/deployment.yaml
+++ b/Api.ResponseCache/.kubernetes/deployment.yaml
@@ -73,6 +73,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.ResponseCache/Api.ResponseCache.Models/Api.ResponseCache.Models.csproj b/Api.ResponseCache/Api.ResponseCache.Models/Api.ResponseCache.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ResponseCache/Api.ResponseCache.Models/Api.ResponseCache.Models.csproj
+++ b/Api.ResponseCache/Api.ResponseCache.Models/Api.ResponseCache.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ResponseCache/Api.ResponseCache/Dockerfile.Local b/Api.ResponseCache/Api.ResponseCache/Dockerfile.Local
index 7062f25b..ef77c5cf 100644
--- a/Api.ResponseCache/Api.ResponseCache/Dockerfile.Local
+++ b/Api.ResponseCache/Api.ResponseCache/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ResponseCache.dll"]
\ No newline at end of file
diff --git a/Api.ResponseCache/Dockerfile b/Api.ResponseCache/Dockerfile
index 3dbc645f..66a2a6df 100644
--- a/Api.ResponseCache/Dockerfile
+++ b/Api.ResponseCache/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.ResponseCompression/.github/workflows/build-and-deploy.yml b/Api.ResponseCompression/.github/workflows/build-and-deploy.yml
index 5006980a..b4538268 100644
--- a/Api.ResponseCompression/.github/workflows/build-and-deploy.yml
+++ b/Api.ResponseCompression/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.ResponseCompression
IMAGE_NAME: api.responsecompression
SERVICE_NAME: api-responsecompression
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.ResponseCompression/.kubernetes/configmap.yaml b/Api.ResponseCompression/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.ResponseCompression/.kubernetes/configmap.yaml
+++ b/Api.ResponseCompression/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.ResponseCompression/.kubernetes/deployment.yaml b/Api.ResponseCompression/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.ResponseCompression/.kubernetes/deployment.yaml
+++ b/Api.ResponseCompression/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.ResponseCompression/Api.ResponseCompression.Models/Api.ResponseCompression.Models.csproj b/Api.ResponseCompression/Api.ResponseCompression.Models/Api.ResponseCompression.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.ResponseCompression/Api.ResponseCompression.Models/Api.ResponseCompression.Models.csproj
+++ b/Api.ResponseCompression/Api.ResponseCompression.Models/Api.ResponseCompression.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.ResponseCompression/Api.ResponseCompression/Dockerfile.Local b/Api.ResponseCompression/Api.ResponseCompression/Dockerfile.Local
index 53c17eb8..02cb186b 100644
--- a/Api.ResponseCompression/Api.ResponseCompression/Dockerfile.Local
+++ b/Api.ResponseCompression/Api.ResponseCompression/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.ResponseCompression.dll"]
\ No newline at end of file
diff --git a/Api.ResponseCompression/Dockerfile b/Api.ResponseCompression/Dockerfile
index e0f4803d..32666ffc 100644
--- a/Api.ResponseCompression/Dockerfile
+++ b/Api.ResponseCompression/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Session/.github/workflows/build-and-deploy.yml b/Api.Session/.github/workflows/build-and-deploy.yml
index 37ef11b0..3102c3e1 100644
--- a/Api.Session/.github/workflows/build-and-deploy.yml
+++ b/Api.Session/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Session
IMAGE_NAME: api.session
SERVICE_NAME: api-session
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Session/.kubernetes/configmap.yaml b/Api.Session/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Session/.kubernetes/configmap.yaml
+++ b/Api.Session/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Session/.kubernetes/deployment.yaml b/Api.Session/.kubernetes/deployment.yaml
index 02882c56..00eb67cf 100644
--- a/Api.Session/.kubernetes/deployment.yaml
+++ b/Api.Session/.kubernetes/deployment.yaml
@@ -73,6 +73,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.Session/Api.Session.Models/Api.Session.Models.csproj b/Api.Session/Api.Session.Models/Api.Session.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Session/Api.Session.Models/Api.Session.Models.csproj
+++ b/Api.Session/Api.Session.Models/Api.Session.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Session/Api.Session/Dockerfile.Local b/Api.Session/Api.Session/Dockerfile.Local
index fb4b06aa..93481dcb 100644
--- a/Api.Session/Api.Session/Dockerfile.Local
+++ b/Api.Session/Api.Session/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Session.dll"]
\ No newline at end of file
diff --git a/Api.Session/Dockerfile b/Api.Session/Dockerfile
index 7b0f7c94..cc1fda5c 100644
--- a/Api.Session/Dockerfile
+++ b/Api.Session/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.StartupTasks/.github/workflows/build-and-deploy.yml b/Api.StartupTasks/.github/workflows/build-and-deploy.yml
index 07fe4bdc..138cb1ab 100644
--- a/Api.StartupTasks/.github/workflows/build-and-deploy.yml
+++ b/Api.StartupTasks/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.StartupTasks
IMAGE_NAME: api.startuptasks
SERVICE_NAME: api-startuptasks
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.StartupTasks/.kubernetes/configmap.yaml b/Api.StartupTasks/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.StartupTasks/.kubernetes/configmap.yaml
+++ b/Api.StartupTasks/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.StartupTasks/.kubernetes/deployment.yaml b/Api.StartupTasks/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.StartupTasks/.kubernetes/deployment.yaml
+++ b/Api.StartupTasks/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.StartupTasks/Api.StartupTasks.Models/Api.StartupTasks.Models.csproj b/Api.StartupTasks/Api.StartupTasks.Models/Api.StartupTasks.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.StartupTasks/Api.StartupTasks.Models/Api.StartupTasks.Models.csproj
+++ b/Api.StartupTasks/Api.StartupTasks.Models/Api.StartupTasks.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.StartupTasks/Api.StartupTasks/Dockerfile.Local b/Api.StartupTasks/Api.StartupTasks/Dockerfile.Local
index 1a5748f0..cd848c63 100644
--- a/Api.StartupTasks/Api.StartupTasks/Dockerfile.Local
+++ b/Api.StartupTasks/Api.StartupTasks/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.StartupTasks.dll"]
\ No newline at end of file
diff --git a/Api.StartupTasks/Dockerfile b/Api.StartupTasks/Dockerfile
index 13ab1f4e..3551b58d 100644
--- a/Api.StartupTasks/Dockerfile
+++ b/Api.StartupTasks/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.StaticFiles/.github/workflows/build-and-deploy.yml b/Api.StaticFiles/.github/workflows/build-and-deploy.yml
index cdc4dcb8..1895d321 100644
--- a/Api.StaticFiles/.github/workflows/build-and-deploy.yml
+++ b/Api.StaticFiles/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.StaticFiles
IMAGE_NAME: api.staticfiles
SERVICE_NAME: api-staticfiles
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.StaticFiles/.kubernetes/configmap.yaml b/Api.StaticFiles/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.StaticFiles/.kubernetes/configmap.yaml
+++ b/Api.StaticFiles/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.StaticFiles/.kubernetes/deployment.yaml b/Api.StaticFiles/.kubernetes/deployment.yaml
index 02882c56..00eb67cf 100644
--- a/Api.StaticFiles/.kubernetes/deployment.yaml
+++ b/Api.StaticFiles/.kubernetes/deployment.yaml
@@ -73,6 +73,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.StaticFiles/Api.StaticFiles.Models/Api.StaticFiles.Models.csproj b/Api.StaticFiles/Api.StaticFiles.Models/Api.StaticFiles.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.StaticFiles/Api.StaticFiles.Models/Api.StaticFiles.Models.csproj
+++ b/Api.StaticFiles/Api.StaticFiles.Models/Api.StaticFiles.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.StaticFiles/Api.StaticFiles/Dockerfile.Local b/Api.StaticFiles/Api.StaticFiles/Dockerfile.Local
index ad327791..93bccd3d 100644
--- a/Api.StaticFiles/Api.StaticFiles/Dockerfile.Local
+++ b/Api.StaticFiles/Api.StaticFiles/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.StaticFiles.dll"]
\ No newline at end of file
diff --git a/Api.StaticFiles/Dockerfile b/Api.StaticFiles/Dockerfile
index ab17eafa..1c0bbf52 100644
--- a/Api.StaticFiles/Dockerfile
+++ b/Api.StaticFiles/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Storage.Azure/.github/workflows/build-and-deploy.yml b/Api.Storage.Azure/.github/workflows/build-and-deploy.yml
index 2b882124..47920047 100644
--- a/Api.Storage.Azure/.github/workflows/build-and-deploy.yml
+++ b/Api.Storage.Azure/.github/workflows/build-and-deploy.yml
@@ -2,35 +2,33 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Storage.Azure
IMAGE_NAME: api.storage.azure
SERVICE_NAME: api-storage-azure
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_GROUP_STORAGE: ${{ vars.AZURE_STORAGE_RESOURCE_GROUP }}
- AZURE_GROUP_BACKUP: ${{ vars.AZURE_BACKUP_RESOURCE_GROUP }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_STORAGE: ${{ vars.AZURE_RESOURCE_GROUP_STORAGE }}
+ AZURE_GROUP_BACKUP: ${{ vars.AZURE_RESOURCE_GROUP_BACKUP }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -40,20 +38,16 @@ env:
KUBERNETES_CPU_SCALING: 180
STORAGE_SIZE: 1000
STORAGE_SHARE_NAME: nano-storage-azure
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -66,26 +60,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ - name: Publish NuGet
+ shell: pwsh
+ run: |
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ - name: Build & Push Image
+ shell: pwsh
+ run: |
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Create Fileshare
shell: pwsh
run: |
@@ -105,72 +138,97 @@ jobs:
--storage-account $env:STORAGE_ACCOUNT_NAME `
--access-tier TransactionOptimized `
--quota $env:STORAGE_SIZE;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- $env:BACKUP_VAULT_NAME = az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
-
- az backup protection enable-for-azurefileshare `
- -g $env:AZURE_GROUP_BACKUP `
- -v $env:BACKUP_VAULT_NAME `
- -p $env:STORAGE_ACCOUNT_NAME-backup-policy `
+ }
+ else
+ {
+ az storage share-rm update `
+ -g $env:AZURE_GROUP_STORAGE `
+ -n $env:STORAGE_SHARE_NAME `
--storage-account $env:STORAGE_ACCOUNT_NAME `
- --azure-file-share $env:STORAGE_SHARE_NAME;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ --access-tier TransactionOptimized `
+ --quota $env:STORAGE_SIZE;
}
- - name: Publish Image
- shell: pwsh
- run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
if ($LastExitCode -ne 0)
{
throw "error";
};
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
+ $env:BACKUP_VAULT_NAME = az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
+
+ az backup protection enable-for-azurefileshare `
+ -g $env:AZURE_GROUP_BACKUP `
+ -v $env:BACKUP_VAULT_NAME `
+ -p $env:STORAGE_ACCOUNT_NAME-fileshare-backup-policy `
+ --storage-account $env:STORAGE_ACCOUNT_NAME `
+ --azure-file-share $env:STORAGE_SHARE_NAME;
+
if ($LastExitCode -ne 0)
{
throw "error";
- };
+ };
- - name: Publish NuGet
+ - name: Managed Identity & Federated Credentials
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- if ($LastExitCode -ne 0)
- {
+ $env:IDENTITY_NAME = $env:SERVICE_NAME + "-identity";
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
+ $env:KUBERNETES_ISSUER_URL = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].['oidcIssuerProfile.issuerUrl'] -o tsv;
+ $env:STORAGE_ACCOUNT_ID = az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].id -o tsv;
+
+ if (-not $env:IDENTITY_PRINCIPAL_ID)
+ {
+ az identity create `
+ -g $env:AZURE_GROUP_KUBERNETES `
+ -n $env:IDENTITY_NAME;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
+ }
+
+ az role assignment create `
+ --assignee-object-id $env:IDENTITY_PRINCIPAL_ID `
+ --assignee-principal-type ServicePrincipal `
+ --role "Storage File Data SMB MI Admin" `
+ --scope $env:STORAGE_ACCOUNT_ID
+
+ if ($LastExitCode -ne 0)
+ {
throw "error";
- };
+ };
+
+ az identity federated-credential create `
+ --name $env:SERVICE_NAME-credentials `
+ --resource-group $env:AZURE_GROUP_KUBERNETES `
+ --identity-name $env:IDENTITY_NAME `
+ --issuer $env:KUBERNETES_ISSUER_URL `
+ --subject "system:serviceaccount:${env:KUBERNETES_NAMESPACE}:${env:SERVICE_NAME}-service-account" `
+ --audience api://AzureADTokenExchange;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ echo "IDENTITY_NAME=$env:IDENTITY_NAME" >> $env:GITHUB_ENV;
- name: Kubernetes Deploy
shell: pwsh
run: |
+ $env:IDENTITY_CLIENT_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query clientId -o tsv;
+ $env:VOLUME_NAME_SUFFIX = $env:IDENTITY_CLIENT_ID.Substring(0, 5);
+
+ Get-Content .kubernetes/service-account.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service-account.tmp.yaml;
+ kubectl apply -f .kubernetes/service-account.tmp.yaml;
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
Get-Content .kubernetes/storage-pv.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/storage-pv.tmp.yaml;
kubectl apply -f .kubernetes/storage-pv.tmp.yaml;
if ($LastExitCode -ne 0)
@@ -214,7 +272,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -222,6 +280,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Storage.Azure/.kubernetes/configmap.yaml b/Api.Storage.Azure/.kubernetes/configmap.yaml
index b64a515d..ef1e83f5 100644
--- a/Api.Storage.Azure/.kubernetes/configmap.yaml
+++ b/Api.Storage.Azure/.kubernetes/configmap.yaml
@@ -1,9 +1,9 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
namespace: %KUBERNETES_NAMESPACE%
data:
App__Version: %VERSION%
- Storage__HealthCheck__AccountName: %STORAGE_ACCOUNT_NAME%
+ Storage__ShareName: %STORAGE_SHARE_NAME%
ASPNETCORE_ENVIRONMENT: %ASPNETCORE_ENVIRONMENT%
diff --git a/Api.Storage.Azure/.kubernetes/deployment.yaml b/Api.Storage.Azure/.kubernetes/deployment.yaml
index 9eb44e22..f2e7ad15 100644
--- a/Api.Storage.Azure/.kubernetes/deployment.yaml
+++ b/Api.Storage.Azure/.kubernetes/deployment.yaml
@@ -15,8 +15,9 @@ spec:
metadata:
labels:
app: %SERVICE_NAME%
+ azure.workload.identity/use: "true"
spec:
- automountServiceAccountToken: false
+ serviceAccountName: %SERVICE_NAME%-service-account
securityContext:
runAsUser: 1000
runAsGroup: 2000
@@ -86,9 +87,7 @@ spec:
volumes:
- name: %SERVICE_NAME%-volume
persistentVolumeClaim:
- claimName: %SERVICE_NAME%-azurefile-pvc
+ claimName: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
- name: tmp
emptyDir: {}
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.Storage.Azure/.kubernetes/service-account.yaml b/Api.Storage.Azure/.kubernetes/service-account.yaml
new file mode 100644
index 00000000..283750fd
--- /dev/null
+++ b/Api.Storage.Azure/.kubernetes/service-account.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: %SERVICE_NAME%-service-account
+ namespace: %KUBERNETES_NAMESPACE%
+ annotations:
+ azure.workload.identity/client-id: %IDENTITY_CLIENT_ID%
\ No newline at end of file
diff --git a/Api.Storage.Azure/.kubernetes/storage-pv.yaml b/Api.Storage.Azure/.kubernetes/storage-pv.yaml
index b6281fb8..5bc60f12 100644
--- a/Api.Storage.Azure/.kubernetes/storage-pv.yaml
+++ b/Api.Storage.Azure/.kubernetes/storage-pv.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: PersistentVolume
metadata:
- name: %SERVICE_NAME%-azurefile-pv
+ name: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
spec:
capacity:
storage: %STORAGE_SIZE%
@@ -9,9 +9,20 @@ spec:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: azurefile-static
+ mountOptions:
+ - dir_mode=0777
+ - file_mode=0777
+ - uid=0
+ - gid=0
+ claimRef:
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ namespace: %KUBERNETES_NAMESPACE%
csi:
driver: file.csi.azure.com
- volumeHandle: %STORAGE_SHARE_NAME%
+ volumeHandle: %AZURE_GROUP_STORAGE%#%STORAGE_ACCOUNT_NAME%#%STORAGE_SHARE_NAME%-%VOLUME_NAME_SUFFIX%
volumeAttributes:
shareName: %STORAGE_SHARE_NAME%
- storageAccount: %STORAGE_ACCOUNT_NAME%
\ No newline at end of file
+ storageAccount: %STORAGE_ACCOUNT_NAME%
+ resourceGroup: %AZURE_GROUP_STORAGE%
+ clientID: %IDENTITY_CLIENT_ID%
+ mountWithWorkloadIdentityToken: "true"
\ No newline at end of file
diff --git a/Api.Storage.Azure/.kubernetes/storage-pvc.yaml b/Api.Storage.Azure/.kubernetes/storage-pvc.yaml
index 252c7857..8ce63544 100644
--- a/Api.Storage.Azure/.kubernetes/storage-pvc.yaml
+++ b/Api.Storage.Azure/.kubernetes/storage-pvc.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
- name: %SERVICE_NAME%-azurefile-pvc
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
namespace: %KUBERNETES_NAMESPACE%
spec:
accessModes:
@@ -9,4 +9,5 @@ spec:
storageClassName: azurefile-static
resources:
requests:
- storage: %STORAGE_SIZE%
\ No newline at end of file
+ storage: %STORAGE_SIZE%
+ volumeName: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
\ No newline at end of file
diff --git a/Api.Storage.Azure/Api.Storage.Azure.Models/Api.Storage.Azure.Models.csproj b/Api.Storage.Azure/Api.Storage.Azure.Models/Api.Storage.Azure.Models.csproj
index 2865dfbb..df88cb1c 100644
--- a/Api.Storage.Azure/Api.Storage.Azure.Models/Api.Storage.Azure.Models.csproj
+++ b/Api.Storage.Azure/Api.Storage.Azure.Models/Api.Storage.Azure.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Storage.Azure/Api.Storage.Azure.sln b/Api.Storage.Azure/Api.Storage.Azure.sln
index a75a6568..11c3e764 100644
--- a/Api.Storage.Azure/Api.Storage.Azure.sln
+++ b/Api.Storage.Azure/Api.Storage.Azure.sln
@@ -22,6 +22,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".kubernetes", ".kubernetes"
.kubernetes\autoscaler.yaml = .kubernetes\autoscaler.yaml
.kubernetes\configmap.yaml = .kubernetes\configmap.yaml
.kubernetes\deployment.yaml = .kubernetes\deployment.yaml
+ .kubernetes\service-account.yaml = .kubernetes\service-account.yaml
.kubernetes\service.yaml = .kubernetes\service.yaml
.kubernetes\storage-pv.yaml = .kubernetes\storage-pv.yaml
.kubernetes\storage-pvc.yaml = .kubernetes\storage-pvc.yaml
diff --git a/Api.Storage.Azure/Api.Storage.Azure/Dockerfile.Local b/Api.Storage.Azure/Api.Storage.Azure/Dockerfile.Local
index eeb40cec..772f5036 100644
--- a/Api.Storage.Azure/Api.Storage.Azure/Dockerfile.Local
+++ b/Api.Storage.Azure/Api.Storage.Azure/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Storage.Azure.dll"]
\ No newline at end of file
diff --git a/Api.Storage.Azure/Api.Storage.Azure/appsettings.json b/Api.Storage.Azure/Api.Storage.Azure/appsettings.json
index 645e4243..2c668037 100644
--- a/Api.Storage.Azure/Api.Storage.Azure/appsettings.json
+++ b/Api.Storage.Azure/Api.Storage.Azure/appsettings.json
@@ -15,8 +15,7 @@
"Storage": {
"ShareName": "nano-storage-azure",
"HealthCheck": {
- "AccountName": null,
- "UnhealthyStatus": "Degraded"
+ "UnhealthyStatus": "Unhealthy"
}
}
}
\ No newline at end of file
diff --git a/Api.Storage.Azure/Dockerfile b/Api.Storage.Azure/Dockerfile
index 6b462057..606c0e91 100644
--- a/Api.Storage.Azure/Dockerfile
+++ b/Api.Storage.Azure/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Storage.Azure/README.md b/Api.Storage.Azure/README.md
index b4382605..d1489d0a 100644
--- a/Api.Storage.Azure/README.md
+++ b/Api.Storage.Azure/README.md
@@ -25,11 +25,13 @@ This application builds on **[Api.Blank](https://github.com/Nano-Core/Nano.Lesso
that inherits from the top-level Nano `BaseController`.
This application demonstrates uploading a file and saving it to a mapped file share.
+
When running locally, files are **NOT** written to the Azure File Share. Instead, Docker mounts a local directory to simulate the file share.
+
Files are saved in `.docker/bin/`.
-A storage health check is configured to target the Azure File Share, but it requires valid credentials to be provided under `Storage.Credentials`. If the
-credentials are omitted from the configuration, the application will still run, but the health-check will report `degraded`.
+A storage health check is configured to target the Azure File Share, but it requires valid credentials to be provided under `Storage.Credentials`. If the credentials are omitted
+from the configuration, the application will still run, but the health-check will report `degraded`.
Open [http://localhost:8080/healthz](http://localhost:8080/healthz) to view the storage health-check JSON response.
@@ -62,8 +64,7 @@ Add the storage configuration.
"Storage": {
"ShareName": "nano-storage-azure",
"HealthCheck": {
- "AccountName": null,
- "UnhealthyStatus": "Degraded"
+ "UnhealthyStatus": "Unhealthy"
}
}
```
@@ -81,18 +82,79 @@ Additionally, application health-checks have been enabled with the configuration
Mapped the fileshare in `docker-compose.yml`.
```yaml
-docker
+services:
+ svc.accounts:
volumes:
- ./bin/nano-storage-azure:/mnt/nano-storage-azure
```
## Kubernetes
-Added two new kubernetes templaets, the `storage-pv.yaml` and `storage-pvc.yaml`. Updated the `deployment.yaml` mounting the volume.
+Added three new kubernetes templaets, the `storage-pv.yaml`, `storage-pvc.yaml`, and the `service-account.yaml`.
+
+```yaml
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
+spec:
+ capacity:
+ storage: %STORAGE_SIZE%
+ accessModes:
+ - ReadWriteMany
+ persistentVolumeReclaimPolicy: Retain
+ storageClassName: azurefile-static
+ mountOptions:
+ - dir_mode=0777
+ - file_mode=0777
+ - uid=0
+ - gid=0
+ claimRef:
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ namespace: %KUBERNETES_NAMESPACE%
+ csi:
+ driver: file.csi.azure.com
+ volumeHandle: %AZURE_GROUP_STORAGE%#%STORAGE_ACCOUNT_NAME%#%STORAGE_SHARE_NAME%-%VOLUME_NAME_SUFFIX%
+ volumeAttributes:
+ shareName: %STORAGE_SHARE_NAME%
+ storageAccount: %STORAGE_ACCOUNT_NAME%
+ resourceGroup: %AZURE_GROUP_STORAGE%
+ clientID: %IDENTITY_CLIENT_ID%
+ mountWithWorkloadIdentityToken: "true"
+```
+
+```yaml
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ namespace: %KUBERNETES_NAMESPACE%
+spec:
+ accessModes:
+ - ReadWriteMany
+ storageClassName: azurefile-static
+ resources:
+ requests:
+ storage: %STORAGE_SIZE%
+ volumeName: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
+```
+
+Also, the `configmap.yaml` should have the share-name included.
+
+```
+data:
+ Storage__ShareName: %STORAGE_SHARE_NAME%
+```
+
+Updated the `deployment.yaml` mounting the volume.
```yaml
spec:
template:
+ metadata:
+ labels:
+ azure.workload.identity/use: "true"
spec:
+ serviceAccountName: %SERVICE_NAME%-service-account
containers:
volumeMounts:
- name: %SERVICE_NAME%-volume
@@ -102,33 +164,34 @@ spec:
volumes:
- name: %SERVICE_NAME%-volume
persistentVolumeClaim:
- claimName: %SERVICE_NAME%-azurefile-pvc
+ claimName: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
- name: tmp
emptyDir: {}
```
-Additionally, the `configmap.yaml` file stores the `$env:STORAGE_ACCOUNT_NAME` value, which is used by the TCP-based health check to validate connectivity to the Azure File Share endpoint.
+Notice the name suffix for `claimName`. The PersistentVolume (PV) and PersistentVolumeClaim (PVC) are created with a suffix to allow the managed identity used for authenticating with the
+Azure File Share to be changed without trying to replace existing immutable resources.
## GitHub Actions
Add the following environment variables to the `buid-and-deply.yml`.
```yaml
-env:
- AZURE_GROUP_BACKUP: ${{ vars.AZURE_BACKUP_RESOURCE_GROUP }}
- AZURE_GROUP_STORAGE: ${{ vars.AZURE_STORAGE_RESOURCE_GROUP }}
+env:
+ AZURE_GROUP_BACKUP: ${{ vars.AZURE_RESOURCE_GROUP_BACKUP }}
+ AZURE_GROUP_STORAGE: ${{ vars.AZURE_RESOURCE_GROUP_STORAGE }}
STORAGE_SIZE: 1000
STORAGE_SHARE_NAME: nano-storage-azure
```
-And add this step below as well, ensuring that the fileshare gets created before the application is deployed.
+Additionally, this step has been added to ensure the file share is created before the application is deployed.
```yaml
- name: Create Fileshare
shell: pwsh
run: |
- $env:STORAGE_ACCOUNT_NAME = sudo az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].name -o tsv;
+ $env:STORAGE_ACCOUNT_NAME = az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].name -o tsv;
- $env:FILE_SHARE_EXISTS = sudo az storage share-rm exists `
+ $env:FILE_SHARE_EXISTS = az storage share-rm exists `
-g $env:AZURE_GROUP_STORAGE `
-n $env:STORAGE_SHARE_NAME `
--storage-account $env:STORAGE_ACCOUNT_NAME `
@@ -136,30 +199,100 @@ And add this step below as well, ensuring that the fileshare gets created before
if ($env:FILE_SHARE_EXISTS -eq "false")
{
- sudo az storage share-rm create `
+ az storage share-rm create `
-g $env:AZURE_GROUP_STORAGE `
-n $env:STORAGE_SHARE_NAME `
--storage-account $env:STORAGE_ACCOUNT_NAME `
--access-tier TransactionOptimized `
--quota $env:STORAGE_SIZE;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ }
+ else
+ {
+ az storage share-rm update `
+ -g $env:AZURE_GROUP_STORAGE `
+ -n $env:STORAGE_SHARE_NAME `
+ --storage-account $env:STORAGE_ACCOUNT_NAME `
+ --access-tier TransactionOptimized `
+ --quota $env:STORAGE_SIZE;
+ }
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
- $env:BACKUP_VAULT_NAME = sudo az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
+ $env:BACKUP_VAULT_NAME = az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
- sudo az backup protection enable-for-azurefileshare `
- -g $env:AZURE_GROUP_BACKUP `
- -v $env:BACKUP_VAULT_NAME `
- -p $env:STORAGE_ACCOUNT_NAME-backup-policy `
- --storage-account $env:STORAGE_ACCOUNT_NAME `
- --azure-file-share $env:STORAGE_SHARE_NAME;
-
- if ($LastExitCode -ne 0)
- {
+ az backup protection enable-for-azurefileshare `
+ -g $env:AZURE_GROUP_BACKUP `
+ -v $env:BACKUP_VAULT_NAME `
+ -p $env:STORAGE_ACCOUNT_NAME-fileshare-backup-policy `
+ --storage-account $env:STORAGE_ACCOUNT_NAME `
+ --azure-file-share $env:STORAGE_SHARE_NAME;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+```
+
+...and includes a step to create a managed identity and federated credentials for authenticating with the storage account.
+
+```
+- name: Managed Identity & Federated Credentials
+ shell: pwsh
+ run: |
+ $env:IDENTITY_NAME = $env:SERVICE_NAME + "-identity";
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
+ $env:KUBERNETES_ISSUER_URL = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].['oidcIssuerProfile.issuerUrl'] -o tsv;
+ $env:STORAGE_ACCOUNT_ID = az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].id -o tsv;
+
+ if (-not $env:IDENTITY_PRINCIPAL_ID)
+ {
+ az identity create `
+ -g $env:AZURE_GROUP_KUBERNETES `
+ -n $env:IDENTITY_NAME;
+
+ if ($LastExitCode -ne 0)
+ {
throw "error";
};
+
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
}
-```
\ No newline at end of file
+
+ az role assignment create `
+ --assignee-object-id $env:IDENTITY_PRINCIPAL_ID `
+ --assignee-principal-type ServicePrincipal `
+ --role "Storage File Data SMB MI Admin" `
+ --scope $env:STORAGE_ACCOUNT_ID
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ az identity federated-credential create `
+ --name $env:SERVICE_NAME-credentials `
+ --resource-group $env:AZURE_GROUP_KUBERNETES `
+ --identity-name $env:IDENTITY_NAME `
+ --issuer $env:KUBERNETES_ISSUER_URL `
+ --subject "system:serviceaccount:${env:KUBERNETES_NAMESPACE}:${env:SERVICE_NAME}-service-account" `
+ --audience api://AzureADTokenExchange;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ echo "IDENTITY_NAME=$env:IDENTITY_NAME" >> $env:GITHUB_ENV;
+```
+
+Last, during the Kubernetes deployment step, before any resources are applied, environmental variables required for the new `stoerage-pv.yaml` and `stoerage-pvc.yaml` must be set.
+
+```powershell
+$env:IDENTITY_CLIENT_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query clientId -o tsv;
+$env:VOLUME_NAME_SUFFIX = $env:IDENTITY_CLIENT_ID.Substring(0, 5);
+```
+
+The deployment commands have been updated to apply the new Kubernetes storage templates.
diff --git a/Api.Storage.Local/.github/workflows/build-and-deploy.yml b/Api.Storage.Local/.github/workflows/build-and-deploy.yml
index 3044ba11..13b0c3d9 100644
--- a/Api.Storage.Local/.github/workflows/build-and-deploy.yml
+++ b/Api.Storage.Local/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Storage.Local
IMAGE_NAME: api.storage.local
SERVICE_NAME: api-storage-local
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -37,20 +35,19 @@ env:
KUBERNETES_CPU_LIMIT: 600m
STORAGE_SIZE: 1000
STORAGE_SHARE_NAME: nano-storage-local
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -63,68 +60,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -171,7 +165,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -179,6 +173,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Storage.Local/.kubernetes/configmap.yaml b/Api.Storage.Local/.kubernetes/configmap.yaml
index 3977c0ee..ef1e83f5 100644
--- a/Api.Storage.Local/.kubernetes/configmap.yaml
+++ b/Api.Storage.Local/.kubernetes/configmap.yaml
@@ -1,8 +1,9 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
namespace: %KUBERNETES_NAMESPACE%
data:
App__Version: %VERSION%
+ Storage__ShareName: %STORAGE_SHARE_NAME%
ASPNETCORE_ENVIRONMENT: %ASPNETCORE_ENVIRONMENT%
diff --git a/Api.Storage.Local/.kubernetes/deployment.yaml b/Api.Storage.Local/.kubernetes/deployment.yaml
index eb1c9093..0fcc7ffb 100644
--- a/Api.Storage.Local/.kubernetes/deployment.yaml
+++ b/Api.Storage.Local/.kubernetes/deployment.yaml
@@ -84,6 +84,3 @@ spec:
claimName: %SERVICE_NAME%-pvc
- name: tmp
emptyDir: {}
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Storage.Local/.kubernetes/storage-storageclass.yaml b/Api.Storage.Local/.kubernetes/storage-storageclass.yaml
index f9ccaa3e..fa2c6dd3 100644
--- a/Api.Storage.Local/.kubernetes/storage-storageclass.yaml
+++ b/Api.Storage.Local/.kubernetes/storage-storageclass.yaml
@@ -2,7 +2,7 @@ apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: %SERVICE_NAME%-storage-class
-provisioner: kubernetes.io/azure-disk
+provisioner: disk.csi.azure.com
parameters:
storageaccounttype: Standard_LRS
kind: Managed
diff --git a/Api.Storage.Local/Api.Storage.Local.Models/Api.Storage.Local.Models.csproj b/Api.Storage.Local/Api.Storage.Local.Models/Api.Storage.Local.Models.csproj
index 8f47aa23..08ff690d 100644
--- a/Api.Storage.Local/Api.Storage.Local.Models/Api.Storage.Local.Models.csproj
+++ b/Api.Storage.Local/Api.Storage.Local.Models/Api.Storage.Local.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Storage.Local/Api.Storage.Local/Dockerfile.Local b/Api.Storage.Local/Api.Storage.Local/Dockerfile.Local
index 6512ea12..2f0019a3 100644
--- a/Api.Storage.Local/Api.Storage.Local/Dockerfile.Local
+++ b/Api.Storage.Local/Api.Storage.Local/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Storage.Local.dll"]
\ No newline at end of file
diff --git a/Api.Storage.Local/Dockerfile b/Api.Storage.Local/Dockerfile
index 657921b0..ceeec3ed 100644
--- a/Api.Storage.Local/Dockerfile
+++ b/Api.Storage.Local/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Storage.Local/README.md b/Api.Storage.Local/README.md
index c243734f..6156afb4 100644
--- a/Api.Storage.Local/README.md
+++ b/Api.Storage.Local/README.md
@@ -57,7 +57,7 @@ Configured the application with the necessary storage setup.
"Storage": {
"ShareName": "nano-storage-local",
"HealthCheck": {
- "UnhealthyStatus": "Degraded"
+ "UnhealthyStatus": "Unhealthy"
}
}
```
@@ -75,7 +75,8 @@ Additionally, application health-checks have been enabled with the configuration
Mapped the fileshare in `docker-compose.yml`.
```yaml
-docker
+services:
+ console.storage.local:
volumes:
- ./bin/nano-storage-local:/mnt/nano-storage-local
```
@@ -113,11 +114,3 @@ env:
```
Deployment commands have also been updated to apply each of the new Kubernetes templates.
-
-```powershell
-Get-Content .kubernetes/{resource-name}.yaml `
- | foreach { [Environment]::ExpandEnvironmentVariables($_) } `
- | Set-Content .kubernetes/{resource-name}.tmp.yaml;
-
-sudo kubectl apply -f .kubernetes/{resource-name}.tmp.yaml;
-```
diff --git a/Api.TimeZone/.github/workflows/build-and-deploy.yml b/Api.TimeZone/.github/workflows/build-and-deploy.yml
index edbde0d8..b1a29486 100644
--- a/Api.TimeZone/.github/workflows/build-and-deploy.yml
+++ b/Api.TimeZone/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.TimeZone
IMAGE_NAME: api.timezone
SERVICE_NAME: api-timezone
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.TimeZone/.kubernetes/configmap.yaml b/Api.TimeZone/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.TimeZone/.kubernetes/configmap.yaml
+++ b/Api.TimeZone/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.TimeZone/.kubernetes/deployment.yaml b/Api.TimeZone/.kubernetes/deployment.yaml
index 02882c56..00eb67cf 100644
--- a/Api.TimeZone/.kubernetes/deployment.yaml
+++ b/Api.TimeZone/.kubernetes/deployment.yaml
@@ -73,6 +73,4 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Api.TimeZone/Api.TimeZone.Models/Api.TimeZone.Models.csproj b/Api.TimeZone/Api.TimeZone.Models/Api.TimeZone.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.TimeZone/Api.TimeZone.Models/Api.TimeZone.Models.csproj
+++ b/Api.TimeZone/Api.TimeZone.Models/Api.TimeZone.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.TimeZone/Api.TimeZone/Dockerfile.Local b/Api.TimeZone/Api.TimeZone/Dockerfile.Local
index 0ab8570b..b64cb62b 100644
--- a/Api.TimeZone/Api.TimeZone/Dockerfile.Local
+++ b/Api.TimeZone/Api.TimeZone/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.TimeZone.dll"]
\ No newline at end of file
diff --git a/Api.TimeZone/Dockerfile b/Api.TimeZone/Dockerfile
index f7c7188e..31423bbd 100644
--- a/Api.TimeZone/Dockerfile
+++ b/Api.TimeZone/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.Versioning/.github/workflows/build-and-deploy.yml b/Api.Versioning/.github/workflows/build-and-deploy.yml
index 3a01b8e4..15a4e398 100644
--- a/Api.Versioning/.github/workflows/build-and-deploy.yml
+++ b/Api.Versioning/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Versioning
IMAGE_NAME: api.versioning
SERVICE_NAME: api-versioning
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.Versioning/.kubernetes/configmap.yaml b/Api.Versioning/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.Versioning/.kubernetes/configmap.yaml
+++ b/Api.Versioning/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.Versioning/.kubernetes/deployment.yaml b/Api.Versioning/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.Versioning/.kubernetes/deployment.yaml
+++ b/Api.Versioning/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.Versioning/Api.Versioning.Models/Api.Versioning.Models.csproj b/Api.Versioning/Api.Versioning.Models/Api.Versioning.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.Versioning/Api.Versioning.Models/Api.Versioning.Models.csproj
+++ b/Api.Versioning/Api.Versioning.Models/Api.Versioning.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.Versioning/Api.Versioning/Dockerfile.Local b/Api.Versioning/Api.Versioning/Dockerfile.Local
index 273713a4..41c3c823 100644
--- a/Api.Versioning/Api.Versioning/Dockerfile.Local
+++ b/Api.Versioning/Api.Versioning/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Versioning.dll"]
\ No newline at end of file
diff --git a/Api.Versioning/Dockerfile b/Api.Versioning/Dockerfile
index 079b95c9..aa2c3f66 100644
--- a/Api.Versioning/Dockerfile
+++ b/Api.Versioning/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api.VirusScan/.github/workflows/build-and-deploy.yml b/Api.VirusScan/.github/workflows/build-and-deploy.yml
index 0e0eb79a..f7338576 100644
--- a/Api.VirusScan/.github/workflows/build-and-deploy.yml
+++ b/Api.VirusScan/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.VirusScan
IMAGE_NAME: api.virusscan
SERVICE_NAME: api-virusscan
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +59,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api.VirusScan/.kubernetes/configmap.yaml b/Api.VirusScan/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api.VirusScan/.kubernetes/configmap.yaml
+++ b/Api.VirusScan/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api.VirusScan/.kubernetes/deployment.yaml b/Api.VirusScan/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Api.VirusScan/.kubernetes/deployment.yaml
+++ b/Api.VirusScan/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api.VirusScan/Api.VirusScan.Models/Api.VirusScan.Models.csproj b/Api.VirusScan/Api.VirusScan.Models/Api.VirusScan.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api.VirusScan/Api.VirusScan.Models/Api.VirusScan.Models.csproj
+++ b/Api.VirusScan/Api.VirusScan.Models/Api.VirusScan.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api.VirusScan/Api.VirusScan/Dockerfile.Local b/Api.VirusScan/Api.VirusScan/Dockerfile.Local
index bcc73a22..a9fc193d 100644
--- a/Api.VirusScan/Api.VirusScan/Dockerfile.Local
+++ b/Api.VirusScan/Api.VirusScan/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.VirusScan.dll"]
\ No newline at end of file
diff --git a/Api.VirusScan/Dockerfile b/Api.VirusScan/Dockerfile
index 6fde6c7c..7ff85e3b 100644
--- a/Api.VirusScan/Dockerfile
+++ b/Api.VirusScan/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Api._Blank/.github/workflows/build-and-deploy.yml b/Api._Blank/.github/workflows/build-and-deploy.yml
index 11902a3d..2ee847e3 100644
--- a/Api._Blank/.github/workflows/build-and-deploy.yml
+++ b/Api._Blank/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Api.Blank
IMAGE_NAME: api.blank
SERVICE_NAME: api-blank
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,18 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,68 +58,65 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
if ($LastExitCode -ne 0)
{
throw "error";
};
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -156,7 +149,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +157,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Api._Blank/.kubernetes/configmap.yaml b/Api._Blank/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Api._Blank/.kubernetes/configmap.yaml
+++ b/Api._Blank/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Api._Blank/.kubernetes/deployment.yaml b/Api._Blank/.kubernetes/deployment.yaml
index b15e7e29..085e7961 100644
--- a/Api._Blank/.kubernetes/deployment.yaml
+++ b/Api._Blank/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Api._Blank/Api.Blank.Models/Api.Blank.Models.csproj b/Api._Blank/Api.Blank.Models/Api.Blank.Models.csproj
index c33a8e9a..e4188943 100644
--- a/Api._Blank/Api.Blank.Models/Api.Blank.Models.csproj
+++ b/Api._Blank/Api.Blank.Models/Api.Blank.Models.csproj
@@ -22,17 +22,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -41,7 +35,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Api._Blank/Api.Blank/Dockerfile.Local b/Api._Blank/Api.Blank/Dockerfile.Local
index 9c84943b..a43abac6 100644
--- a/Api._Blank/Api.Blank/Dockerfile.Local
+++ b/Api._Blank/Api.Blank/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Api.Blank.dll"]
\ No newline at end of file
diff --git a/Api._Blank/Dockerfile b/Api._Blank/Dockerfile
index c06b6792..ce52c1c9 100644
--- a/Api._Blank/Dockerfile
+++ b/Api._Blank/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Console.CustomConfigSection/.github/workflows/build-and-deploy.yml b/Console.CustomConfigSection/.github/workflows/build-and-deploy.yml
index 930c99ac..96bdd122 100644
--- a/Console.CustomConfigSection/.github/workflows/build-and-deploy.yml
+++ b/Console.CustomConfigSection/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.CustomConfigSection
IMAGE_NAME: console.customconfigsection
SERVICE_NAME: console-customconfigsection
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.CustomConfigSection/.kubernetes/cronjob.yaml b/Console.CustomConfigSection/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.CustomConfigSection/.kubernetes/cronjob.yaml
+++ b/Console.CustomConfigSection/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.CustomService/.github/workflows/build-and-deploy.yml b/Console.CustomService/.github/workflows/build-and-deploy.yml
index 784ed671..2fbe6222 100644
--- a/Console.CustomService/.github/workflows/build-and-deploy.yml
+++ b/Console.CustomService/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.CustomService
IMAGE_NAME: console.customservice
SERVICE_NAME: console-customservice
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.CustomService/.kubernetes/cronjob.yaml b/Console.CustomService/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.CustomService/.kubernetes/cronjob.yaml
+++ b/Console.CustomService/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Data.InMemory/.github/workflows/build-and-deploy.yml b/Console.Data.InMemory/.github/workflows/build-and-deploy.yml
index 9733b697..62befd94 100644
--- a/Console.Data.InMemory/.github/workflows/build-and-deploy.yml
+++ b/Console.Data.InMemory/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,49 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Data.InMemory
IMAGE_NAME: console.data.inmemory
SERVICE_NAME: console-data-inmemory
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/Nano-Core/Nano.Template.Console
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +57,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +122,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +130,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Data.InMemory/.kubernetes/cronjob.yaml b/Console.Data.InMemory/.kubernetes/cronjob.yaml
index 71ff564c..e10e9bd5 100644
--- a/Console.Data.InMemory/.kubernetes/cronjob.yaml
+++ b/Console.Data.InMemory/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Data.InMemory/Console.Data.InMemory/appsettings.json b/Console.Data.InMemory/Console.Data.InMemory/appsettings.json
index 254689c8..e0008651 100644
--- a/Console.Data.InMemory/Console.Data.InMemory/appsettings.json
+++ b/Console.Data.InMemory/Console.Data.InMemory/appsettings.json
@@ -17,7 +17,7 @@
"DefaultCollation": null,
"ConnectionString": "nanoDb",
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
diff --git a/Console.Data.InMemory/README.md b/Console.Data.InMemory/README.md
index d6cb69d4..5515d9ac 100644
--- a/Console.Data.InMemory/README.md
+++ b/Console.Data.InMemory/README.md
@@ -61,7 +61,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": "nanoDb",
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
diff --git a/Console.Data.MySql/.github/workflows/build-and-deploy.yml b/Console.Data.MySql/.github/workflows/build-and-deploy.yml
index 7e45a90a..98282ad2 100644
--- a/Console.Data.MySql/.github/workflows/build-and-deploy.yml
+++ b/Console.Data.MySql/.github/workflows/build-and-deploy.yml
@@ -2,31 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Data.MySql
IMAGE_NAME: console.data.mysql
SERVICE_NAME: console-data-mysql
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/Nano-Core/Nano.Template.Console
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
@@ -35,22 +35,21 @@ env:
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -63,75 +62,76 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
$env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
$env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
+
$userExists = mysql `
--host $env:SQL_HOST `
--port $env:SQL_PORT `
@@ -160,7 +160,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
Get-Content .kubernetes/sql-auth-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/sql-auth-secret.tmp.yaml;
kubectl apply -f .kubernetes/sql-auth-secret.tmp.yaml;
@@ -184,7 +184,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -192,6 +192,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Data.MySql/.kubernetes/auth-sql-secret.yaml b/Console.Data.MySql/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Console.Data.MySql/.kubernetes/auth-sql-secret.yaml
+++ b/Console.Data.MySql/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Console.Data.MySql/.kubernetes/cronjob.yaml b/Console.Data.MySql/.kubernetes/cronjob.yaml
index 9ae388c3..a5d8b30b 100644
--- a/Console.Data.MySql/.kubernetes/cronjob.yaml
+++ b/Console.Data.MySql/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -53,5 +54,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Data.MySql/Console.Data.MySql/appsettings.Development.json b/Console.Data.MySql/Console.Data.MySql/appsettings.Development.json
index 34379ce9..670c9b68 100644
--- a/Console.Data.MySql/Console.Data.MySql/appsettings.Development.json
+++ b/Console.Data.MySql/Console.Data.MySql/appsettings.Development.json
@@ -1,6 +1,6 @@
{
"Data": {
"StartupAction": "Migrate",
- "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=sa;Pwd=myPassword_123"
+ "ConnectionString": "Server=host.docker.internal;Database=nanoDb;Uid=root;Pwd=myPassword_123"
}
}
\ No newline at end of file
diff --git a/Console.Data.MySql/README.md b/Console.Data.MySql/README.md
index 7d5948c4..d19e08da 100644
--- a/Console.Data.MySql/README.md
+++ b/Console.Data.MySql/README.md
@@ -107,7 +107,7 @@ services:
```
## Kubernetes
-Added the `%SERVICE_NAME%-secret` for the connectionstring to the `cronjob.yaml`.
+Added the `auth-sql-secret.yaml` for the connectionstring to the `cronjob.yaml`.
```json
spec:
@@ -129,6 +129,8 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
+ DOTNET_EF_TOOLS_VERSION: "10.0"
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
@@ -141,34 +143,56 @@ Additionally, this step has been added to ensure database migrations are applied
- name: Database Migration & User
shell: pwsh
run: |
- $env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName;
- $env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort;
- $env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Preferred";
+ $env:SQL_HOST = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].fullyQualifiedDomainName -o tsv;
+ $env:SQL_PORT = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].databasePort -o tsv;
+ $env:SQL_ADMIN_USER = az mysql flexible-server list -g $env:AZURE_GROUP_DATABASE --query [0].administratorLogin -o tsv;
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING ";
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_ADMIN_USER;Pwd=$env:SQL_ADMIN_PASSWORD;SslMode=Required";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
+ --no-build `
+ --configuration Release `
+ --startup-project $env:APP_NAME `
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
- apt-get update;
- apt-get install -y mysql-client;
+ $env:MYSQL_PWD = $env:SQL_ADMIN_PASSWORD
- $userExists = mysql --batch -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '$env:SQL_USER');" $env:SQL_MIGRATION_CONNECTIONSTRING;
+ $userExists = mysql `
+ --host $env:SQL_HOST `
+ --port $env:SQL_PORT `
+ --user $env:SQL_ADMIN_USER `
+ --ssl-mode=REQUIRED `
+ -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '$env:SQL_USER');";
if ($userExists -eq 0)
{
- mysql --connect-expired-password -e " `
- CREATE USER '$env:SQL_USER'@'%' IDENTIFIED BY '$env:SQL_PASSWORD'; `
- GRANT SELECT, INSERT, UPDATE, DELETE ON $database.* TO '$env:SQL_USER'@'%'; `
- FLUSH PRIVILEGES;" $env:SQL_MIGRATION_CONNECTIONSTRING;
+ mysql `
+ --host $env:SQL_HOST `
+ --port $env:SQL_PORT `
+ --user $env:SQL_ADMIN_USER `
+ --ssl-mode=REQUIRED `
+ -e "CREATE USER '$env:SQL_USER'@'%' IDENTIFIED BY '$env:SQL_PASSWORD'; GRANT SELECT, INSERT, UPDATE, DELETE ON $env:SQL_NAME.* TO '$env:SQL_USER'@'%'; FLUSH PRIVILEGES;";
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
}
+
+ echo "SQL_HOST=$env:SQL_HOST" >> $env:GITHUB_ENV;
+ echo "SQL_PORT=$env:SQL_PORT" >> $env:GITHUB_ENV;
```
-Last, an additional template has been added to the deployment for storing the application connectionstring in a Kuberntes secret.
+Last, before applying the new Kubernetes templates, these environmental variables must be set.
+
+```powershell
+$env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Required";
+```
+Finally, apply the templates.
diff --git a/Console.Data.PostgreSQL/.github/workflows/build-and-deploy.yml b/Console.Data.PostgreSQL/.github/workflows/build-and-deploy.yml
index 8e9abbbf..fa0d8692 100644
--- a/Console.Data.PostgreSQL/.github/workflows/build-and-deploy.yml
+++ b/Console.Data.PostgreSQL/.github/workflows/build-and-deploy.yml
@@ -2,55 +2,54 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Data.PostgreSQL
IMAGE_NAME: console.data.postgresql
SERVICE_NAME: console-data-postgresql
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/Nano-Core/Nano.Template.Console
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-mysql-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -63,77 +62,74 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ ./
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Database Migration & User
shell: pwsh
run: |
$env:SQL_HOST = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "5432";
$env:SQL_ADMIN_USER = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].username" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Prefer;Trust Server Certificate=true";
+ $env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Require;Trust Server Certificate=true";
+
+ $env:DATA__CONNECTIONSTRING = $env:SQL_MIGRATION_CONNECTIONSTRING;
- dotnet ef database update `
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
-
- apt-get update
- apt-get install -y postgresql-client
$userExists = psql "$env:SQL_MIGRATION_CONNECTIONSTRING" `
-tAc "SELECT 1 FROM pg_roles WHERE rolname='$env:SQL_USER';"
@@ -168,7 +164,7 @@ jobs:
- name: Kubernetes Deploy
shell: pwsh
run: |
- $env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Uid=$env:SQL_USER;Pwd=$env:SQL_PASSWORD;SslMode=Preferred";
+ $env:SQL_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_USER;Password=$env:SQL_PASSWORD;SSL Mode=Require;Trust Server Certificate=true";
Get-Content .kubernetes/auth-sql-secret.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/auth-sql-secret.tmp.yaml;
kubectl apply -f .kubernetes/auth-sql-secret.tmp.yaml;
@@ -192,7 +188,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -200,6 +196,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml b/Console.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Console.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml
+++ b/Console.Data.PostgreSQL/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Console.Data.PostgreSQL/.kubernetes/cronjob.yaml b/Console.Data.PostgreSQL/.kubernetes/cronjob.yaml
index 9ae388c3..a5d8b30b 100644
--- a/Console.Data.PostgreSQL/.kubernetes/cronjob.yaml
+++ b/Console.Data.PostgreSQL/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -53,5 +54,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Data.PostgreSQL/README.md b/Console.Data.PostgreSQL/README.md
index d27443e3..963e46ba 100644
--- a/Console.Data.PostgreSQL/README.md
+++ b/Console.Data.PostgreSQL/README.md
@@ -105,7 +105,7 @@ services:
```
## Kubernetes
-Added the `%SERVICE_NAME%-secret` for the connectionstring to the `cronjob.yaml`.
+Added the `auth-sql-secret.yaml` for the connectionstring to the `cronjob.yaml`.
```json
spec:
@@ -125,6 +125,8 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
+ DOTNET_EF_TOOLS_VERSION: "10.0"
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
SQL_NAME: nanoDb
SQL_USER: api-data-postgres-user
SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
@@ -142,18 +144,19 @@ Additionally, this step has been added to ensure database migrations are applied
$env:SQL_ADMIN_USER = az postgres flexible-server list -g $env:AZURE_GROUP_DATABASE --query "[0].username" -o tsv;
$env:SQL_MIGRATION_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;SSL Mode=Prefer;Trust Server Certificate=true";
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
+ $env:DATA__CONNECTIONSTRING = $env:SQL_MIGRATION_CONNECTIONSTRING;
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
+ --no-build `
+ --configuration Release `
+ --startup-project $env:APP_NAME `
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
-
- apt-get update
- apt-get install -y postgresql-client
$userExists = psql "$env:SQL_MIGRATION_CONNECTIONSTRING" `
-tAc "SELECT 1 FROM pg_roles WHERE rolname='$env:SQL_USER';"
@@ -181,6 +184,15 @@ Additionally, this step has been added to ensure database migrations are applied
psql "$env:SQL_MIGRATION_CONNECTIONSTRING" `
-c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO $env:SQL_USER;"
}
+
+ echo "SQL_HOST=$env:SQL_HOST" >> $env:GITHUB_ENV;
+ echo "SQL_PORT=$env:SQL_PORT" >> $env:GITHUB_ENV;
+```
+
+Last, before applying the new Kubernetes templates, these environmental variables must be set.
+
+```powershell
+$env:SQL_CONNECTIONSTRING = "Host=$env:SQL_HOST;Port=$env:SQL_PORT;Database=$env:SQL_NAME;Username=$env:SQL_USER;Password=$env:SQL_PASSWORD;SSL Mode=Require;Trust Server Certificate=true";
```
-Last, an additional template has been added to the deployment for storing the application connectionstring in a Kuberntes secret.
+Finally, apply the templates.
diff --git a/Console.Data.SqLite/.github/workflows/build-and-deploy.yml b/Console.Data.SqLite/.github/workflows/build-and-deploy.yml
index 86a7f66c..14c0c429 100644
--- a/Console.Data.SqLite/.github/workflows/build-and-deploy.yml
+++ b/Console.Data.SqLite/.github/workflows/build-and-deploy.yml
@@ -2,54 +2,50 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Data.SqLite
IMAGE_NAME: console.data.sqlite
SERVICE_NAME: console-data-sqlite
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/Nano-Core/Nano.Template.Console
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- SQL_NAME: nanoDb
SQL_SIZE: 10Gi
- SQL_CONNECTIONSTRING: "Data Source=/mnt/data/{{ env.SQL_NAME }}.sqlite"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,69 +58,52 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ ./
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Database Migration
- shell: pwsh
- run: |
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
- name: Kubernetes Deploy
shell: pwsh
@@ -158,7 +137,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -166,6 +145,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Data.SqLite/.kubernetes/cronjob.yaml b/Console.Data.SqLite/.kubernetes/cronjob.yaml
index aa4f8991..1dd91868 100644
--- a/Console.Data.SqLite/.kubernetes/cronjob.yaml
+++ b/Console.Data.SqLite/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -54,5 +55,3 @@ spec:
persistentVolumeClaim:
claimName: %SERVICE_NAME%-pvc
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Data.SqLite/.kubernetes/data-pvc.yaml b/Console.Data.SqLite/.kubernetes/data-pvc.yaml
index 0b9d4415..f3a52c3c 100644
--- a/Console.Data.SqLite/.kubernetes/data-pvc.yaml
+++ b/Console.Data.SqLite/.kubernetes/data-pvc.yaml
@@ -2,10 +2,11 @@ apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: %SERVICE_NAME%-data-pvc
+ namespace: %KUBERNETES_NAMESPACE%
spec:
accessModes:
- ReadWriteOnce
storageClassName: %SERVICE_NAME%-data-storage-class
resources:
requests:
- storage: %DATA_SIZE%
\ No newline at end of file
+ storage: %SQL_SIZE%
\ No newline at end of file
diff --git a/Console.Data.SqLite/.kubernetes/data-storageclass.yaml b/Console.Data.SqLite/.kubernetes/data-storageclass.yaml
index 47530cdc..2f66693c 100644
--- a/Console.Data.SqLite/.kubernetes/data-storageclass.yaml
+++ b/Console.Data.SqLite/.kubernetes/data-storageclass.yaml
@@ -2,7 +2,7 @@ apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: %SERVICE_NAME%-data-storage-class
-provisioner: kubernetes.io/azure-disk
+provisioner: disk.csi.azure.com
parameters:
storageaccounttype: Standard_LRS
kind: Managed
diff --git a/Console.Data.SqLite/Console.Data.SqLite/appsettings.Development.json b/Console.Data.SqLite/Console.Data.SqLite/appsettings.Development.json
index 8927ff99..8593c62d 100644
--- a/Console.Data.SqLite/Console.Data.SqLite/appsettings.Development.json
+++ b/Console.Data.SqLite/Console.Data.SqLite/appsettings.Development.json
@@ -1,5 +1,2 @@
{
- "Data": {
- "StartupAction": "Migrate"
- }
}
\ No newline at end of file
diff --git a/Console.Data.SqLite/README.md b/Console.Data.SqLite/README.md
index 7661aa11..69fd89ca 100644
--- a/Console.Data.SqLite/README.md
+++ b/Console.Data.SqLite/README.md
@@ -65,7 +65,7 @@ Configured the application with the necessary data setup.
"DefaultCollation": null,
"ConnectionString": "Data Source=/data/nanoDb.sqlite",
"Repository": {
- "UseAutoSave": false,
+ "UseAutoSave": true,
"QueryIncludeDepth": 4
},
"Identity": null,
@@ -74,13 +74,7 @@ Configured the application with the necessary data setup.
}
```
-...and `appsettings.Development.json`
-
-```json
-"Data": {
- "StartupAction": "Migrate",
-}
-```
+> ⚠️ **Notice:** `StartupAction` is set to `migrate` in all environments. This may cause the pod to restart during the initial deployment.
## Docker Compose
Added SqLite as a service dependency in `docker-compose.yml`.
@@ -93,7 +87,7 @@ services:
```
## Kubernetes
-Added two additional kubernetes templates, `storageclass.yaml` and `pvc.yaml`, for dynamically manage and creating the disk for the SqLite database.
+Added two additional kubernetes templates, `data-storageclass.yaml` and `data-pvc.yaml`, for dynamically manage and creating the disk for the SqLite database.
Also, updated `cronjob.yaml` adding the volumes and volume mounts.
@@ -118,34 +112,7 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
- SQL_NAME: nanoDb
SQL_SIZE: 10Gi
- SQL_CONNECTIONSTRING: "Data Source=/mnt/data/{{ env.nanoDb }}.sqlite"
-```
-
-Additionally, this step has been added to ensure database migrations are applied.
-
-```yaml
-- name: Database Migration
- shell: pwsh
- run: |
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING" `;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
```
Deployment commands have also been updated to apply each of the new Kubernetes templates.
-
-```powershell
-Get-Content .kubernetes/{resource-name}.yaml `
- | foreach { [Environment]::ExpandEnvironmentVariables($_) } `
- | Set-Content .kubernetes/{resource-name}.tmp.yaml;
-
-sudo kubectl apply -f .kubernetes/{resource-name}.tmp.yaml;
-```
diff --git a/Console.Data.SqlServer/.github/workflows/build-and-deploy.yml b/Console.Data.SqlServer/.github/workflows/build-and-deploy.yml
index 054564d4..fa8a17ac 100644
--- a/Console.Data.SqlServer/.github/workflows/build-and-deploy.yml
+++ b/Console.Data.SqlServer/.github/workflows/build-and-deploy.yml
@@ -2,55 +2,54 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Data.SqlServer
IMAGE_NAME: console.data.sqlserver
SERVICE_NAME: console-data-sqlserver
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
+ DOTNET_EF_TOOLS_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
SQL_NAME: nanoDb
SQL_USER: api-data-sqlserver-user
- SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
- SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ SQL_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
+ SQL_ADMIN_PASSWORD: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_SQL_ADMIN_PASSWORD || secrets.STAGING_SQL_ADMIN_PASSWORD }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -63,57 +62,52 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
- name: Database Migration & User
shell: pwsh
@@ -121,26 +115,26 @@ jobs:
$env:SQL_HOST = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "1433"
$env:SQL_ADMIN_USER = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].administratorLogin" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
- dotnet ef database update `
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
--no-build `
+ --configuration Release `
--startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
throw "error";
};
-
- apt-get update
- apt-get install -y mssql-tools unixodbc-dev
$loginExists = sqlcmd `
-S "$env:SQL_HOST,$env:SQL_PORT" `
-U $env:SQL_ADMIN_USER `
-P $env:SQL_ADMIN_PASSWORD `
- -d master `
+ -d main `
-h -1 `
-Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
@@ -150,7 +144,7 @@ jobs:
-S "$env:SQL_HOST,$env:SQL_PORT" `
-U $env:SQL_ADMIN_USER `
-P $env:SQL_ADMIN_PASSWORD `
- -d master `
+ -d main `
-Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
};
@@ -204,7 +198,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -212,6 +206,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Data.SqlServer/.kubernetes/auth-sql-secret.yaml b/Console.Data.SqlServer/.kubernetes/auth-sql-secret.yaml
index fffa83c4..9e6a2303 100644
--- a/Console.Data.SqlServer/.kubernetes/auth-sql-secret.yaml
+++ b/Console.Data.SqlServer/.kubernetes/auth-sql-secret.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
- name: $env:SERVICE_NAME-sql-auth-secret
+ name: %SERVICE_NAME%-sql-auth-secret
namespace: %KUBERNETES_NAMESPACE%
type: Opaque
stringData:
diff --git a/Console.Data.SqlServer/.kubernetes/cronjob.yaml b/Console.Data.SqlServer/.kubernetes/cronjob.yaml
index 9ae388c3..a5d8b30b 100644
--- a/Console.Data.SqlServer/.kubernetes/cronjob.yaml
+++ b/Console.Data.SqlServer/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -53,5 +54,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Data.SqlServer/README.md b/Console.Data.SqlServer/README.md
index cdae2e12..cb9b51ec 100644
--- a/Console.Data.SqlServer/README.md
+++ b/Console.Data.SqlServer/README.md
@@ -104,7 +104,7 @@ services:
```
## Kubernetes
-Added the `%SERVICE_NAME%-secret` for the connectionstring to the `cronjob.yaml`.
+Added the `auth-sql-secret.yaml` for the connectionstring to the `cronjob.yaml`.
```json
spec:
@@ -126,6 +126,8 @@ Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
+ DOTNET_EF_TOOLS_VERSION: "10.0"
+ AZURE_GROUP_DATABASE : ${{ vars.AZURE_RESOURCE_GROUP_DATABASE }}
SQL_NAME: nanoDb
SQL_USER: api-data-sqlserver-user
SQL_PASSWORD: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_SQL_NANO_DB_PASSWORD || secrets.STAGING_SQL_NANO_DB_PASSWORD }}
@@ -141,12 +143,15 @@ Additionally, this step has been added to ensure database migrations are applied
$env:SQL_HOST = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].fullyQualifiedDomainName" -o tsv;
$env:SQL_PORT = "1433"
$env:SQL_ADMIN_USER = az sql server list -g $env:AZURE_GROUP_DATABASE --query "[0].administratorLogin" -o tsv;
- $env:SQL_MIGRATION_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
- dotnet ef database update `
- --no-build `
- --startup-project $env:APP_NAME `
- --connection "$env:SQL_MIGRATION_CONNECTIONSTRING";
+ $env:DATA__CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_ADMIN_USER;Password=$env:SQL_ADMIN_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
+
+ & "/opt/ef-tools/$env:DOTNET_EF_TOOLS_VERSION/dotnet-ef" database update `
+ --no-build `
+ --configuration Release `
+ --startup-project $env:APP_NAME `
+ -- `
+ --environment $env:ASPNETCORE_ENVIRONMENT;
if ($LastExitCode -ne 0)
{
@@ -157,42 +162,51 @@ Additionally, this step has been added to ensure database migrations are applied
apt-get install -y mssql-tools unixodbc-dev
$loginExists = sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d master `
- -h -1 `
- -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d main `
+ -h -1 `
+ -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.server_principals WHERE name = '$env:SQL_USER';"
if ($loginExists -eq 0)
{
sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d master `
- -Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d main `
+ -Q "CREATE LOGIN [$env:SQL_USER] WITH PASSWORD = '$env:SQL_PASSWORD';"
};
$userExists = sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d $env:SQL_NAME `
- -h -1 `
- -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.database_principals WHERE name = '$env:SQL_USER';"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d $env:SQL_NAME `
+ -h -1 `
+ -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.database_principals WHERE name = '$env:SQL_USER';"
if ($userExists -eq 0)
{
sqlcmd `
- -S "$env:SQL_HOST,$env:SQL_PORT" `
- -U $env:SQL_ADMIN_USER `
- -P $env:SQL_ADMIN_PASSWORD `
- -d $env:SQL_NAME `
- -Q "CREATE USER [$env:SQL_USER] FOR LOGIN [$env:SQL_USER];
- ALTER ROLE db_datareader ADD MEMBER [$env:SQL_USER];
- ALTER ROLE db_datawriter ADD MEMBER [$env:SQL_USER];"
+ -S "$env:SQL_HOST,$env:SQL_PORT" `
+ -U $env:SQL_ADMIN_USER `
+ -P $env:SQL_ADMIN_PASSWORD `
+ -d $env:SQL_NAME `
+ -Q "CREATE USER [$env:SQL_USER] FOR LOGIN [$env:SQL_USER];
+ ALTER ROLE db_datareader ADD MEMBER [$env:SQL_USER];
+ ALTER ROLE db_datawriter ADD MEMBER [$env:SQL_USER];"
};
+
+ echo "SQL_HOST=$env:SQL_HOST" >> $env:GITHUB_ENV;
+ echo "SQL_PORT=$env:SQL_PORT" >> $env:GITHUB_ENV;
+```
+
+Last, before applying the new Kubernetes templates, these environmental variables must be set.
+
+```powershell
+$env:SQL_CONNECTIONSTRING = "Server=$env:SQL_HOST,$env:SQL_PORT;Database=$env:SQL_NAME;User Id=$env:SQL_USER;Password=$env:SQL_PASSWORD;Encrypt=True;TrustServerCertificate=True;";
```
-Last, an additional template has been added to the deployment for storing the application connectionstring in a Kuberntes secret.
+Finally, the templates can be applied.
diff --git a/Console.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml b/Console.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml
index 0233cbe7..4627dde2 100644
--- a/Console.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml
+++ b/Console.Eventing.RabbitMq/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Eventing.RabbitMq
IMAGE_NAME: console.eventing.rabbitmq
SERVICE_NAME: console-eventing-rabbitmq
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Eventing.RabbitMq/.kubernetes/cronjob.yaml b/Console.Eventing.RabbitMq/.kubernetes/cronjob.yaml
index 44ab91fe..f373d966 100644
--- a/Console.Eventing.RabbitMq/.kubernetes/cronjob.yaml
+++ b/Console.Eventing.RabbitMq/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -27,16 +28,26 @@ spec:
image: %CONTAINER_REGISTRY_HOST%/%IMAGE_NAME%:%VERSION%
imagePullPolicy: Always
env:
- - name: Eventing__Credentials__Id
- valueFrom:
- secretKeyRef:
- name: rabbitmq-auth
- key: username
- - name: Eventing__Credentials__Secret
- valueFrom:
- secretKeyRef:
- name: rabbitmq-auth
- key: password
+ - name: Eventing__Credentials__Host
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: host
+ - name: Eventing__Credentials__Port
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: port
+ - name: Eventing__Credentials__Id
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: username
+ - name: Eventing__Credentials__Secret
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: password
envFrom:
- configMapRef:
name: %SERVICE_NAME%-config
@@ -58,5 +69,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Eventing.RabbitMq/README.md b/Console.Eventing.RabbitMq/README.md
index d0a49baa..3a8fd651 100644
--- a/Console.Eventing.RabbitMq/README.md
+++ b/Console.Eventing.RabbitMq/README.md
@@ -104,23 +104,34 @@ services:
## Kubernetes
Added the `rabbitmq` secret for password to the `cronjob.yaml`.
-```json
+```yaml
spec:
- template:
+ jobTemplate:
spec:
- containers:
- env:
- - name: Eventing__Credentials__Id
- valueFrom:
- secretKeyRef:
- name: rabbitmq-auth
- key: username
- envFrom:
- - name: Eventing__Credentials__Secret
- valueFrom:
- secretKeyRef:
- name: rabbitmq-auth
- key: password
+ template:
+ spec:
+ containers:
+ env:
+ - name: Eventing__Credentials__Host
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: host
+ - name: Eventing__Credentials__Port
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: port
+ - name: Eventing__Credentials__Id
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: username
+ - name: Eventing__Credentials__Secret
+ valueFrom:
+ secretKeyRef:
+ name: rabbitmq-default-user
+ key: password
```
> ⚠️ The `rabbitmq` secret is created alongside the **[Nano Azure Kubernetes Eventing](https://github.com/Nano-Core/Nano.Azure.Kubernetes/tree/master/Nano.Azure.Kubernetes.RabbitMQ)**
diff --git a/Console.ExceptionHandling/.github/workflows/build-and-deploy.yml b/Console.ExceptionHandling/.github/workflows/build-and-deploy.yml
index 0ad7df32..3c4d5ad2 100644
--- a/Console.ExceptionHandling/.github/workflows/build-and-deploy.yml
+++ b/Console.ExceptionHandling/.github/workflows/build-and-deploy.yml
@@ -2,50 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.ExceptionHandling
IMAGE_NAME: console.exceptionhandling
SERVICE_NAME: console-exceptionhandling
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -58,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -127,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -135,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.ExceptionHandling/.kubernetes/cronjob.yaml b/Console.ExceptionHandling/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.ExceptionHandling/.kubernetes/cronjob.yaml
+++ b/Console.ExceptionHandling/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Localization/.github/workflows/build-and-deploy.yml b/Console.Localization/.github/workflows/build-and-deploy.yml
index aacf89be..5071ea98 100644
--- a/Console.Localization/.github/workflows/build-and-deploy.yml
+++ b/Console.Localization/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Localization
IMAGE_NAME: console.localization
SERVICE_NAME: console-localization
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Localization/.kubernetes/cronjob.yaml b/Console.Localization/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.Localization/.kubernetes/cronjob.yaml
+++ b/Console.Localization/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Logging.Log4Net/.github/workflows/build-and-deploy.yml b/Console.Logging.Log4Net/.github/workflows/build-and-deploy.yml
index 4dc97976..ee633969 100644
--- a/Console.Logging.Log4Net/.github/workflows/build-and-deploy.yml
+++ b/Console.Logging.Log4Net/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Logging.Log4Net
IMAGE_NAME: console.logging.log4net
SERVICE_NAME: console-logging-log4net
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Logging.Log4Net/.kubernetes/cronjob.yaml b/Console.Logging.Log4Net/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.Logging.Log4Net/.kubernetes/cronjob.yaml
+++ b/Console.Logging.Log4Net/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Logging.Microsoft/.github/workflows/build-and-deploy.yml b/Console.Logging.Microsoft/.github/workflows/build-and-deploy.yml
index 1c105bb3..ad5eb89c 100644
--- a/Console.Logging.Microsoft/.github/workflows/build-and-deploy.yml
+++ b/Console.Logging.Microsoft/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Logging.Microsoft
IMAGE_NAME: console.logging.microsoft
SERVICE_NAME: console-logging-microsoft
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Logging.Microsoft/.kubernetes/cronjob.yaml b/Console.Logging.Microsoft/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.Logging.Microsoft/.kubernetes/cronjob.yaml
+++ b/Console.Logging.Microsoft/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Logging.NLog/.github/workflows/build-and-deploy.yml b/Console.Logging.NLog/.github/workflows/build-and-deploy.yml
index 01436524..50d2f923 100644
--- a/Console.Logging.NLog/.github/workflows/build-and-deploy.yml
+++ b/Console.Logging.NLog/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Logging.NLog
IMAGE_NAME: console.logging.nlog
SERVICE_NAME: console-logging-nlog
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Logging.NLog/.kubernetes/cronjob.yaml b/Console.Logging.NLog/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.Logging.NLog/.kubernetes/cronjob.yaml
+++ b/Console.Logging.NLog/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Logging.Serilog/.github/workflows/build-and-deploy.yml b/Console.Logging.Serilog/.github/workflows/build-and-deploy.yml
index fb5412b5..a66649ba 100644
--- a/Console.Logging.Serilog/.github/workflows/build-and-deploy.yml
+++ b/Console.Logging.Serilog/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Logging.Serilog
IMAGE_NAME: console.logging.serilog
SERVICE_NAME: console-logging-serilog
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Logging.Serilog/.kubernetes/cronjob.yaml b/Console.Logging.Serilog/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.Logging.Serilog/.kubernetes/cronjob.yaml
+++ b/Console.Logging.Serilog/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.StartupTasks/.github/workflows/build-and-deploy.yml b/Console.StartupTasks/.github/workflows/build-and-deploy.yml
index 80e559e4..7d431b48 100644
--- a/Console.StartupTasks/.github/workflows/build-and-deploy.yml
+++ b/Console.StartupTasks/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.StartupTasks
IMAGE_NAME: console.startuptasks
SERVICE_NAME: console-startuptasks
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.StartupTasks/.kubernetes/cronjob.yaml b/Console.StartupTasks/.kubernetes/cronjob.yaml
index 32007e73..e10e9bd5 100644
--- a/Console.StartupTasks/.kubernetes/cronjob.yaml
+++ b/Console.StartupTasks/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
\ No newline at end of file
diff --git a/Console.Storage.Azure/.github/workflows/build-and-deploy.yml b/Console.Storage.Azure/.github/workflows/build-and-deploy.yml
index 140653e8..cdd6852f 100644
--- a/Console.Storage.Azure/.github/workflows/build-and-deploy.yml
+++ b/Console.Storage.Azure/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Storage.Azure
IMAGE_NAME: console.storage.azure
SERVICE_NAME: console-storage-azure
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_GROUP_STORAGE: ${{ vars.AZURE_RESOURCE_GROUP_STORAGE }}
AZURE_GROUP_BACKUP: ${{ vars.AZURE_RESOURCE_GROUP_BACKUP }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
@@ -37,20 +35,19 @@ env:
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
STORAGE_SIZE: 1000
STORAGE_SHARE_NAME: nano-storage-azure
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -63,26 +60,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
+ - name: Build & Push Image
+ shell: pwsh
+ run: |
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Create Fileshare
shell: pwsh
run: |
@@ -102,61 +126,97 @@ jobs:
--storage-account $env:STORAGE_ACCOUNT_NAME `
--access-tier TransactionOptimized `
--quota $env:STORAGE_SIZE;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- $env:BACKUP_VAULT_NAME = az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
-
- az backup protection enable-for-azurefileshare `
- -g $env:AZURE_GROUP_BACKUP `
- -v $env:BACKUP_VAULT_NAME `
- -p $env:STORAGE_ACCOUNT_NAME-backup-policy `
+ }
+ else
+ {
+ az storage share-rm update `
+ -g $env:AZURE_GROUP_STORAGE `
+ -n $env:STORAGE_SHARE_NAME `
--storage-account $env:STORAGE_ACCOUNT_NAME `
- --azure-file-share $env:STORAGE_SHARE_NAME;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ --access-tier TransactionOptimized `
+ --quota $env:STORAGE_SIZE;
}
- - name: Publish Image
- shell: pwsh
- run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
-
if ($LastExitCode -ne 0)
{
throw "error";
};
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
+ $env:BACKUP_VAULT_NAME = az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
+
+ az backup protection enable-for-azurefileshare `
+ -g $env:AZURE_GROUP_BACKUP `
+ -v $env:BACKUP_VAULT_NAME `
+ -p $env:STORAGE_ACCOUNT_NAME-fileshare-backup-policy `
+ --storage-account $env:STORAGE_ACCOUNT_NAME `
+ --azure-file-share $env:STORAGE_SHARE_NAME;
+
if ($LastExitCode -ne 0)
{
throw "error";
- };
+ };
+
+ - name: Managed Identity & Federated Credentials
+ shell: pwsh
+ run: |
+ $env:IDENTITY_NAME = $env:SERVICE_NAME + "-identity";
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
+ $env:KUBERNETES_ISSUER_URL = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].['oidcIssuerProfile.issuerUrl'] -o tsv;
+ $env:STORAGE_ACCOUNT_ID = az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].id -o tsv;
+
+ if (-not $env:IDENTITY_PRINCIPAL_ID)
+ {
+ az identity create `
+ -g $env:AZURE_GROUP_KUBERNETES `
+ -n $env:IDENTITY_NAME;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
+ }
+
+ az role assignment create `
+ --assignee-object-id $env:IDENTITY_PRINCIPAL_ID `
+ --assignee-principal-type ServicePrincipal `
+ --role "Storage File Data SMB MI Admin" `
+ --scope $env:STORAGE_ACCOUNT_ID
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ az identity federated-credential create `
+ --name $env:SERVICE_NAME-credentials `
+ --resource-group $env:AZURE_GROUP_KUBERNETES `
+ --identity-name $env:IDENTITY_NAME `
+ --issuer $env:KUBERNETES_ISSUER_URL `
+ --subject "system:serviceaccount:${env:KUBERNETES_NAMESPACE}:${env:SERVICE_NAME}-service-account" `
+ --audience api://AzureADTokenExchange;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ echo "IDENTITY_NAME=$env:IDENTITY_NAME" >> $env:GITHUB_ENV;
- name: Kubernetes Deploy
shell: pwsh
run: |
+ $env:IDENTITY_CLIENT_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query clientId -o tsv;
+ $env:VOLUME_NAME_SUFFIX = $env:IDENTITY_CLIENT_ID.Substring(0, 5);
+
+ Get-Content .kubernetes/service-account.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service-account.tmp.yaml;
+ kubectl apply -f .kubernetes/service-account.tmp.yaml;
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
Get-Content .kubernetes/storage-pv.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/storage-pv.tmp.yaml;
kubectl apply -f .kubernetes/storage-pv.tmp.yaml;
if ($LastExitCode -ne 0)
@@ -186,7 +246,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -194,6 +254,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Storage.Azure/.kubernetes/configmap.yaml b/Console.Storage.Azure/.kubernetes/configmap.yaml
index f2293b0f..dbc85e41 100644
--- a/Console.Storage.Azure/.kubernetes/configmap.yaml
+++ b/Console.Storage.Azure/.kubernetes/configmap.yaml
@@ -5,4 +5,5 @@ metadata:
namespace: %KUBERNETES_NAMESPACE%
data:
App__Version: %VERSION%
+ Storage__ShareName: %STORAGE_SHARE_NAME%
DOTNET_ENVIRONMENT: %DOTNET_ENVIRONMENT%
\ No newline at end of file
diff --git a/Console.Storage.Azure/.kubernetes/cronjob.yaml b/Console.Storage.Azure/.kubernetes/cronjob.yaml
index ea18271f..b66eabf7 100644
--- a/Console.Storage.Azure/.kubernetes/cronjob.yaml
+++ b/Console.Storage.Azure/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -11,10 +12,11 @@ spec:
metadata:
labels:
app: %SERVICE_NAME%
+ azure.workload.identity/use: "true"
spec:
template:
spec:
- automountServiceAccountToken: false
+ serviceAccountName: %SERVICE_NAME%-service-account
securityContext:
runAsUser: 1000
runAsGroup: 2000
@@ -55,10 +57,8 @@ spec:
volumes:
- name: %SERVICE_NAME%-volume
persistentVolumeClaim:
- claimName: %SERVICE_NAME%-azurefile-pvc
+ claimName: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
- name: tmp
emptyDir: {}
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console.Storage.Azure/.kubernetes/service-account.yaml b/Console.Storage.Azure/.kubernetes/service-account.yaml
new file mode 100644
index 00000000..283750fd
--- /dev/null
+++ b/Console.Storage.Azure/.kubernetes/service-account.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: %SERVICE_NAME%-service-account
+ namespace: %KUBERNETES_NAMESPACE%
+ annotations:
+ azure.workload.identity/client-id: %IDENTITY_CLIENT_ID%
\ No newline at end of file
diff --git a/Console.Storage.Azure/.kubernetes/storage-pv.yaml b/Console.Storage.Azure/.kubernetes/storage-pv.yaml
index b6281fb8..5bc60f12 100644
--- a/Console.Storage.Azure/.kubernetes/storage-pv.yaml
+++ b/Console.Storage.Azure/.kubernetes/storage-pv.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: PersistentVolume
metadata:
- name: %SERVICE_NAME%-azurefile-pv
+ name: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
spec:
capacity:
storage: %STORAGE_SIZE%
@@ -9,9 +9,20 @@ spec:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: azurefile-static
+ mountOptions:
+ - dir_mode=0777
+ - file_mode=0777
+ - uid=0
+ - gid=0
+ claimRef:
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ namespace: %KUBERNETES_NAMESPACE%
csi:
driver: file.csi.azure.com
- volumeHandle: %STORAGE_SHARE_NAME%
+ volumeHandle: %AZURE_GROUP_STORAGE%#%STORAGE_ACCOUNT_NAME%#%STORAGE_SHARE_NAME%-%VOLUME_NAME_SUFFIX%
volumeAttributes:
shareName: %STORAGE_SHARE_NAME%
- storageAccount: %STORAGE_ACCOUNT_NAME%
\ No newline at end of file
+ storageAccount: %STORAGE_ACCOUNT_NAME%
+ resourceGroup: %AZURE_GROUP_STORAGE%
+ clientID: %IDENTITY_CLIENT_ID%
+ mountWithWorkloadIdentityToken: "true"
\ No newline at end of file
diff --git a/Console.Storage.Azure/.kubernetes/storage-pvc.yaml b/Console.Storage.Azure/.kubernetes/storage-pvc.yaml
index 252c7857..8ce63544 100644
--- a/Console.Storage.Azure/.kubernetes/storage-pvc.yaml
+++ b/Console.Storage.Azure/.kubernetes/storage-pvc.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
- name: %SERVICE_NAME%-azurefile-pvc
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
namespace: %KUBERNETES_NAMESPACE%
spec:
accessModes:
@@ -9,4 +9,5 @@ spec:
storageClassName: azurefile-static
resources:
requests:
- storage: %STORAGE_SIZE%
\ No newline at end of file
+ storage: %STORAGE_SIZE%
+ volumeName: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
\ No newline at end of file
diff --git a/Console.Storage.Azure/Console.Storage.Azure.sln b/Console.Storage.Azure/Console.Storage.Azure.sln
index 63806ffa..3d54515f 100644
--- a/Console.Storage.Azure/Console.Storage.Azure.sln
+++ b/Console.Storage.Azure/Console.Storage.Azure.sln
@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".kubernetes", ".kubernetes"
ProjectSection(SolutionItems) = preProject
.kubernetes\configmap.yaml = .kubernetes\configmap.yaml
.kubernetes\cronjob.yaml = .kubernetes\cronjob.yaml
+ .kubernetes\service-account.yaml = .kubernetes\service-account.yaml
.kubernetes\storage-pv.yaml = .kubernetes\storage-pv.yaml
.kubernetes\storage-pvc.yaml = .kubernetes\storage-pvc.yaml
EndProjectSection
diff --git a/Console.Storage.Azure/README.md b/Console.Storage.Azure/README.md
index 3731aeef..b3bfe794 100644
--- a/Console.Storage.Azure/README.md
+++ b/Console.Storage.Azure/README.md
@@ -52,39 +52,105 @@ Configured the application with the necessary storage setup.
Mapped the fileshare in `docker-compose.yml`.
```yaml
-docker
+services:
+ svc.accounts:
volumes:
- ./bin/nano-storage-azure:/mnt/nano-storage-azure
```
## Kubernetes
-Added two new kubernetes templaets, the `storage-pv.yaml` and `storage-pvc.yaml`. Updated the `cronjob.yaml` mounting the volume.
+Added three new kubernetes templaets, the `storage-pv.yaml`, `storage-pvc.yaml`, and the `service-account.yaml`.
```yaml
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
spec:
- template:
+ capacity:
+ storage: %STORAGE_SIZE%
+ accessModes:
+ - ReadWriteMany
+ persistentVolumeReclaimPolicy: Retain
+ storageClassName: azurefile-static
+ mountOptions:
+ - dir_mode=0777
+ - file_mode=0777
+ - uid=0
+ - gid=0
+ claimRef:
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ namespace: %KUBERNETES_NAMESPACE%
+ csi:
+ driver: file.csi.azure.com
+ volumeHandle: %AZURE_GROUP_STORAGE%#%STORAGE_ACCOUNT_NAME%#%STORAGE_SHARE_NAME%-%VOLUME_NAME_SUFFIX%
+ volumeAttributes:
+ shareName: %STORAGE_SHARE_NAME%
+ storageAccount: %STORAGE_ACCOUNT_NAME%
+ resourceGroup: %AZURE_GROUP_STORAGE%
+ clientID: %IDENTITY_CLIENT_ID%
+ mountWithWorkloadIdentityToken: "true"
+```
+
+```yaml
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ namespace: %KUBERNETES_NAMESPACE%
+spec:
+ accessModes:
+ - ReadWriteMany
+ storageClassName: azurefile-static
+ resources:
+ requests:
+ storage: %STORAGE_SIZE%
+ volumeName: %SERVICE_NAME%-azurefile-pv-%VOLUME_NAME_SUFFIX%
+```
+
+Also, the `configmap.yaml` should have the share-name included.
+
+```
+data:
+ Storage__ShareName: %STORAGE_SHARE_NAME%
+```
+
+Updated the `cronjob.yaml` mounting the volume.
+
+```yaml
+spec:
+ jobTemplate:
+ metadata:
+ labels:
+ azure.workload.identity/use: "true"
spec:
- containers:
- volumeMounts:
- - name: %SERVICE_NAME%-volume
- mountPath: /mnt/%STORAGE_SHARE_NAME%
- - name: tmp
- mountPath: /tmp
- volumes:
- - name: %SERVICE_NAME%-volume
- persistentVolumeClaim:
- claimName: %SERVICE_NAME%-azurefile-pvc
- - name: tmp
- emptyDir: {}
+ template:
+ spec:
+ serviceAccountName: %SERVICE_NAME%-service-account
+ containers:
+ volumeMounts:
+ - name: %SERVICE_NAME%-volume
+ mountPath: /mnt/%STORAGE_SHARE_NAME%
+ - name: tmp
+ mountPath: /tmp
+ volumes:
+ - name: %SERVICE_NAME%-volume
+ persistentVolumeClaim:
+ claimName: %SERVICE_NAME%-azurefile-pvc-%VOLUME_NAME_SUFFIX%
+ - name: tmp
+ emptyDir: {}
```
+Notice the name suffix for `claimName`. The PersistentVolume (PV) and PersistentVolumeClaim (PVC) are created with a suffix to allow the managed identity used for authenticating with the
+Azure File Share to be changed without trying to replace existing immutable resources.
+
## GitHub Actions
Add the following environment variables to the `buid-and-deply.yml`.
```yaml
env:
- AZURE_GROUP_BACKUP: ${{ vars.AZURE_BACKUP_RESOURCE_GROUP }}
- AZURE_GROUP_STORAGE: ${{ vars.AZURE_STORAGE_RESOURCE_GROUP }}
+ AZURE_GROUP_BACKUP: ${{ vars.AZURE_RESOURCE_GROUP_BACKUP }}
+ AZURE_GROUP_STORAGE: ${{ vars.AZURE_RESOURCE_GROUP_STORAGE }}
STORAGE_SIZE: 1000
STORAGE_SHARE_NAME: nano-storage-azure
```
@@ -95,9 +161,9 @@ Additionally, this step has been added to ensure the file share is created befor
- name: Create Fileshare
shell: pwsh
run: |
- $env:STORAGE_ACCOUNT_NAME = sudo az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].name -o tsv;
+ $env:STORAGE_ACCOUNT_NAME = az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].name -o tsv;
- $env:FILE_SHARE_EXISTS = sudo az storage share-rm exists `
+ $env:FILE_SHARE_EXISTS = az storage share-rm exists `
-g $env:AZURE_GROUP_STORAGE `
-n $env:STORAGE_SHARE_NAME `
--storage-account $env:STORAGE_ACCOUNT_NAME `
@@ -105,30 +171,100 @@ Additionally, this step has been added to ensure the file share is created befor
if ($env:FILE_SHARE_EXISTS -eq "false")
{
- sudo az storage share-rm create `
+ az storage share-rm create `
-g $env:AZURE_GROUP_STORAGE `
-n $env:STORAGE_SHARE_NAME `
--storage-account $env:STORAGE_ACCOUNT_NAME `
--access-tier TransactionOptimized `
--quota $env:STORAGE_SIZE;
-
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
+ }
+ else
+ {
+ az storage share-rm update `
+ -g $env:AZURE_GROUP_STORAGE `
+ -n $env:STORAGE_SHARE_NAME `
+ --storage-account $env:STORAGE_ACCOUNT_NAME `
+ --access-tier TransactionOptimized `
+ --quota $env:STORAGE_SIZE;
+ }
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
- $env:BACKUP_VAULT_NAME = sudo az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
+ $env:BACKUP_VAULT_NAME = az backup vault list -g $env:AZURE_GROUP_BACKUP --query [0].name -o tsv;
- sudo az backup protection enable-for-azurefileshare `
- -g $env:AZURE_GROUP_BACKUP `
- -v $env:BACKUP_VAULT_NAME `
- -p $env:STORAGE_ACCOUNT_NAME-backup-policy `
- --storage-account $env:STORAGE_ACCOUNT_NAME `
- --azure-file-share $env:STORAGE_SHARE_NAME;
-
- if ($LastExitCode -ne 0)
- {
+ az backup protection enable-for-azurefileshare `
+ -g $env:AZURE_GROUP_BACKUP `
+ -v $env:BACKUP_VAULT_NAME `
+ -p $env:STORAGE_ACCOUNT_NAME-fileshare-backup-policy `
+ --storage-account $env:STORAGE_ACCOUNT_NAME `
+ --azure-file-share $env:STORAGE_SHARE_NAME;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+```
+
+...and includes a step to create a managed identity and federated credentials for authenticating with the storage account.
+
+```
+- name: Managed Identity & Federated Credentials
+ shell: pwsh
+ run: |
+ $env:IDENTITY_NAME = $env:SERVICE_NAME + "-identity";
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
+ $env:KUBERNETES_ISSUER_URL = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].['oidcIssuerProfile.issuerUrl'] -o tsv;
+ $env:STORAGE_ACCOUNT_ID = az storage account list -g $env:AZURE_GROUP_STORAGE --query [0].id -o tsv;
+
+ if (-not $env:IDENTITY_PRINCIPAL_ID)
+ {
+ az identity create `
+ -g $env:AZURE_GROUP_KUBERNETES `
+ -n $env:IDENTITY_NAME;
+
+ if ($LastExitCode -ne 0)
+ {
throw "error";
};
+
+ $env:IDENTITY_PRINCIPAL_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query principalId -o tsv;
}
-```
\ No newline at end of file
+
+ az role assignment create `
+ --assignee-object-id $env:IDENTITY_PRINCIPAL_ID `
+ --assignee-principal-type ServicePrincipal `
+ --role "Storage File Data SMB MI Admin" `
+ --scope $env:STORAGE_ACCOUNT_ID
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ az identity federated-credential create `
+ --name $env:SERVICE_NAME-credentials `
+ --resource-group $env:AZURE_GROUP_KUBERNETES `
+ --identity-name $env:IDENTITY_NAME `
+ --issuer $env:KUBERNETES_ISSUER_URL `
+ --subject "system:serviceaccount:${env:KUBERNETES_NAMESPACE}:${env:SERVICE_NAME}-service-account" `
+ --audience api://AzureADTokenExchange;
+
+ if ($LastExitCode -ne 0)
+ {
+ throw "error";
+ };
+
+ echo "IDENTITY_NAME=$env:IDENTITY_NAME" >> $env:GITHUB_ENV;
+```
+
+Last, during the Kubernetes deployment step, before any resources are applied, environmental variables required for the new `stoerage-pv.yaml` and `stoerage-pvc.yaml` must be set.
+
+```powershell
+$env:IDENTITY_CLIENT_ID = az identity show -g $env:AZURE_GROUP_KUBERNETES -n $env:IDENTITY_NAME --query clientId -o tsv;
+$env:VOLUME_NAME_SUFFIX = $env:IDENTITY_CLIENT_ID.Substring(0, 5);
+```
+
+The deployment commands have been updated to apply the new Kubernetes storage templates.
diff --git a/Console.Storage.Local/.github/workflows/build-and-deploy.yml b/Console.Storage.Local/.github/workflows/build-and-deploy.yml
index 236021f4..6cb61dd1 100644
--- a/Console.Storage.Local/.github/workflows/build-and-deploy.yml
+++ b/Console.Storage.Local/.github/workflows/build-and-deploy.yml
@@ -2,31 +2,29 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Storage.Local
IMAGE_NAME: console.storage.local
SERVICE_NAME: console-storage-local
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
@@ -35,20 +33,19 @@ env:
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
STORAGE_SIZE: 1000
STORAGE_SHARE_NAME: nano-storage-local
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -61,57 +58,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -144,7 +137,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -152,6 +145,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Storage.Local/.kubernetes/configmap.yaml b/Console.Storage.Local/.kubernetes/configmap.yaml
index f2293b0f..dbc85e41 100644
--- a/Console.Storage.Local/.kubernetes/configmap.yaml
+++ b/Console.Storage.Local/.kubernetes/configmap.yaml
@@ -5,4 +5,5 @@ metadata:
namespace: %KUBERNETES_NAMESPACE%
data:
App__Version: %VERSION%
+ Storage__ShareName: %STORAGE_SHARE_NAME%
DOTNET_ENVIRONMENT: %DOTNET_ENVIRONMENT%
\ No newline at end of file
diff --git a/Console.Storage.Local/.kubernetes/cronjob.yaml b/Console.Storage.Local/.kubernetes/cronjob.yaml
index 0604cbad..514379a1 100644
--- a/Console.Storage.Local/.kubernetes/cronjob.yaml
+++ b/Console.Storage.Local/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -51,13 +52,9 @@ spec:
mountPath: /mnt/%STORAGE_SHARE_NAME%
- name: tmp
mountPath: /tmp
- restartPolicy: OnFailure
volumes:
- - name: %STORAGE_SHARE_NAME%
- emptyDir: {}
+ - name: %SERVICE_NAME%-volume
+ persistentVolumeClaim:
+ claimName: %SERVICE_NAME%-pvc
- name: tmp
emptyDir: {}
- imagePullSecrets:
- - name: ghcr-pull-secret
-
-
diff --git a/Console.Storage.Local/.kubernetes/storage-storageclass.yaml b/Console.Storage.Local/.kubernetes/storage-storageclass.yaml
index f9ccaa3e..fa2c6dd3 100644
--- a/Console.Storage.Local/.kubernetes/storage-storageclass.yaml
+++ b/Console.Storage.Local/.kubernetes/storage-storageclass.yaml
@@ -2,7 +2,7 @@ apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: %SERVICE_NAME%-storage-class
-provisioner: kubernetes.io/azure-disk
+provisioner: disk.csi.azure.com
parameters:
storageaccounttype: Standard_LRS
kind: Managed
diff --git a/Console.Storage.Local/README.md b/Console.Storage.Local/README.md
index f8b0ac76..4e93cfd3 100644
--- a/Console.Storage.Local/README.md
+++ b/Console.Storage.Local/README.md
@@ -51,7 +51,8 @@ Configured the application with the necessary storage setup.
Mapped the fileshare in `docker-compose.yml`.
```yaml
-docker
+services:
+ console.storage.local:
volumes:
- ./bin/nano-storage-local:/mnt/nano-storage-local
```
@@ -63,20 +64,22 @@ Also, updated `cronjob.yaml` adding the volumes and volume mounts.
```yaml
spec:
- template:
+ jobTemplate:
spec:
- containers:
- volumeMounts:
- - name: %SERVICE_NAME%-volume
- mountPath: /mnt/%STORAGE_SHARE_NAME%
- - name: tmp
- mountPath: /tmp
- volumes:
- - name: %SERVICE_NAME%-volume
- persistentVolumeClaim:
- claimName: %SERVICE_NAME%-pvc
- - name: tmp
- emptyDir: {}
+ template:
+ spec:
+ containers:
+ volumeMounts:
+ - name: %SERVICE_NAME%-volume
+ mountPath: /mnt/%STORAGE_SHARE_NAME%
+ - name: tmp
+ mountPath: /tmp
+ volumes:
+ - name: %SERVICE_NAME%-volume
+ persistentVolumeClaim:
+ claimName: %SERVICE_NAME%-pvc
+ - name: tmp
+ emptyDir: {}
```
## GitHub Actions
@@ -89,11 +92,3 @@ env:
```
Deployment commands have also been updated to apply each of the new Kubernetes templates.
-
-```powershell
-Get-Content .kubernetes/{resource-name}.yaml `
- | foreach { [Environment]::ExpandEnvironmentVariables($_) } `
- | Set-Content .kubernetes/{resource-name}.tmp.yaml;
-
-sudo kubectl apply -f .kubernetes/{resource-name}.tmp.yaml;
-```
diff --git a/Console.Workers/.github/workflows/build-and-deploy.yml b/Console.Workers/.github/workflows/build-and-deploy.yml
index 16aadd83..ded38bde 100644
--- a/Console.Workers/.github/workflows/build-and-deploy.yml
+++ b/Console.Workers/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Workers
IMAGE_NAME: console.workers
SERVICE_NAME: console-workers
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console.Workers/.kubernetes/cronjob.yaml b/Console.Workers/.kubernetes/cronjob.yaml
index 503cd99a..cbd97e65 100644
--- a/Console.Workers/.kubernetes/cronjob.yaml
+++ b/Console.Workers/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,7 +48,5 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Console._Blank/.github/workflows/build-and-deploy.yml b/Console._Blank/.github/workflows/build-and-deploy.yml
index 4a3c8b1d..88a23e95 100644
--- a/Console._Blank/.github/workflows/build-and-deploy.yml
+++ b/Console._Blank/.github/workflows/build-and-deploy.yml
@@ -2,51 +2,48 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Console.Blank
IMAGE_NAME: console.blank
SERVICE_NAME: console-blank
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
KUBERNETES_REPLICA_HISTORY_COUNT: 4
KUBERNETES_MEMORY_REQUEST: 256Mi
KUBERNETES_MEMORY_LIMIT: 768Mi
KUBERNETES_CPU_REQUEST: 50m
KUBERNETES_CPU_LIMIT: 150m
KUBERNETES_CRONJOB_SCHEDULE: "0 * * * *"
- DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ DOTNET_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
+ packages: read
contents: write
- packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -59,57 +56,53 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
- throw "error";
+ throw "error";
};
- - name: Publish Image
+ - name: Build & Push Image
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
--build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
--build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
--build-arg NUGET_HOST=$env:NUGET_HOST `
--build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
--build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ ./
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
@@ -128,7 +121,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -136,6 +129,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Console._Blank/.kubernetes/cronjob.yaml b/Console._Blank/.kubernetes/cronjob.yaml
index 71ff564c..e10e9bd5 100644
--- a/Console._Blank/.kubernetes/cronjob.yaml
+++ b/Console._Blank/.kubernetes/cronjob.yaml
@@ -2,6 +2,7 @@ apiVersion: batch/v1
kind: CronJob
metadata:
name: %SERVICE_NAME%
+ namespace: %KUBERNETES_NAMESPACE%
spec:
schedule: %KUBERNETES_CRONJOB_SCHEDULE%
concurrencyPolicy: Forbid
@@ -47,5 +48,3 @@ spec:
drop:
- ALL
restartPolicy: OnFailure
- imagePullSecrets:
- - name: ghcr-pull-secret
diff --git a/Web._Blank/.github/workflows/build-and-deploy.yml b/Web._Blank/.github/workflows/build-and-deploy.yml
index ec5d0318..a9caa035 100644
--- a/Web._Blank/.github/workflows/build-and-deploy.yml
+++ b/Web._Blank/.github/workflows/build-and-deploy.yml
@@ -2,33 +2,31 @@ name: Build And Deploy
on:
pull_request:
branches:
- - master
+ - main
push:
branches:
- - master
+ - main
+ workflow_dispatch:
env:
APP_NAME: Web.Blank
IMAGE_NAME: web.blank
SERVICE_NAME: web-blank
VERSION: '${{ vars.VERSION }}.${{ github.run_number }}.${{ github.run_attempt }}'
- DOTNET_SDK_VERSION: 10.0
- DOTNET_ASPNET_VERSION: 10.0
+ DOTNET_SDK_VERSION: "10.0"
+ DOTNET_ASPNET_VERSION: "10.0"
AZURE_GROUP_KUBERNETES: ${{ vars.AZURE_RESOURCE_GROUP_KUBERNETES }}
+ AZURE_GROUP_DELIVERY: ${{ vars.AZURE_RESOURCE_GROUP_DELIVERY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/master' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_AZURE_SUBSCRIPTION_ID || secrets.STAGING_AZURE_SUBSCRIPTION_ID }}
NUGET_HOST: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
NUGET_USERNAME: ${{ github.actor }}
NUGET_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_HOST: ghcr.io
- CONTAINER_REGISTRY_USERNAME: ${{ github.actor }}
- CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
- CONTAINER_REGISTRY_SOURCE_LABEL: https://github.com/${{ github.repository }}
KUBERNETES_NODEPOOL_COMPUTE: cpu
- KUBERNETES_NAMESPACE: apps
- KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/master' && 3 || 2 }}
- KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/master' && 8 || 5 }}
+ KUBERNETES_NAMESPACE: ${{ vars.KUBERNETES_NAMESPACE }}
+ KUBERNETES_REPLICA_COUNT: ${{ github.ref == 'refs/heads/main' && 3 || 2 }}
+ KUBERNETES_REPLICA_COUNT_MAX: ${{ github.ref == 'refs/heads/main' && 8 || 5 }}
KUBERNETES_REPLICA_HISTORY_COUNT: 0
KUBERNETES_MEMORY_REQUEST: 512Mi
KUBERNETES_MEMORY_LIMIT: 1536Mi
@@ -36,20 +34,19 @@ env:
KUBERNETES_CPU_REQUEST: 200m
KUBERNETES_CPU_LIMIT: 600m
KUBERNETES_CPU_SCALING: 180
- ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ ASPNETCORE_ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
+concurrency:
+ group: ${{ github.workflow }}-${{ github.repository }}
+ cancel-in-progress: true
jobs:
build-and-deploy:
runs-on:
- self-hosted
- linux
- - ${{ github.ref == 'refs/heads/master' && 'Production' || 'Staging' }}
+ - ${{ github.ref == 'refs/heads/main' && 'Production' || 'Staging' }}
permissions:
contents: write
packages: write
- id-token: write
- concurrency:
- group: ${{ github.repository }}
- cancel-in-progress: true
steps:
- uses: actions/checkout@v6
@@ -62,72 +59,69 @@ jobs:
$env:KUBERNETES_CLUSTER = az aks list -g $env:AZURE_GROUP_KUBERNETES --query [0].name -o tsv;
az aks get-credentials -g $env:AZURE_GROUP_KUBERNETES -n $env:KUBERNETES_CLUSTER --overwrite -o none;
- - name: Build
+ - name: Build Solution
shell: pwsh
run: |
dotnet nuget add source $env:NUGET_HOST -n private -u $env:NUGET_USERNAME -p $env:NUGET_PASSWORD --store-password-in-clear-text;
dotnet build -c Release .\$env:APP_NAME.sln;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Test
+ - name: Test Solution
shell: pwsh
run: |
dotnet test .\.tests\Tests.$env:APP_NAME\Tests.$env:APP_NAME.csproj;
+
if ($LastExitCode -ne 0)
{
throw "error";
};
- - name: Publish Image
+ - name: Publish NuGet
shell: pwsh
run: |
- $registryHost = $env:CONTAINER_REGISTRY_HOST.ToLower()
- $imageLatestTag = $registryHost + "/" + $env:IMAGE_NAME + ":latest";
- $imageVersionTag = $registryHost + "/" + $env:IMAGE_NAME + ":" + $env:VERSION
-
- docker build `
- -t $imageLatestTag `
- -t $imageVersionTag `
- --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
- --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
- --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=$env:CONTAINER_REGISTRY_SOURCE_LABEL `
- --build-arg NUGET_HOST=$env:NUGET_HOST `
- --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
- --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
- ./;
+ $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
+ dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
+ dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
if ($LastExitCode -ne 0)
{
throw "error";
};
- echo $env:CONTAINER_REGISTRY_PASSWORD | docker login $env:CONTAINER_REGISTRY_HOST -u $env:CONTAINER_REGISTRY_USERNAME --password-stdin;
- docker push $imageLatestTag;
- docker push $imageVersionTag;
- if ($LastExitCode -ne 0)
- {
- throw "error";
- };
-
- - name: Publish NuGet
+ - name: Build & Push Image
shell: pwsh
run: |
- $nugetProjectModels=$env:APP_NAME + ".Models/" + $env:APP_NAME + ".Models.csproj";
- dotnet pack $nugetProjectModels -c Release --output nupkgs /p:PackageVersion=$env:VERSION --include-symbols --no-build;
- dotnet nuget push nupkgs/$env:APP_NAME".Models."$env:VERSION.nupkg -s $env:NUGET_HOST -k $env:NUGET_PASSWORD;
+ $env:CONTAINER_REGISTRY_HOST = az acr list -g $env:AZURE_GROUP_DELIVERY --query [0].loginServer -o tsv;
+
+ az acr build `
+ --registry $env:CONTAINER_REGISTRY_HOST `
+ --agent-pool buildpool `
+ -t "$($env:IMAGE_NAME):latest" `
+ -t "$($env:IMAGE_NAME):$($env:VERSION)" `
+ --build-arg DOTNET_SDK_VERSION=$env:DOTNET_SDK_VERSION `
+ --build-arg DOTNET_ASPNET_VERSION=$env:DOTNET_ASPNET_VERSION `
+ --build-arg CONTAINER_REGISTRY_SOURCE_LABEL=https://github.com/$env:GITHUB_REPOSITORY `
+ --build-arg NUGET_HOST=$env:NUGET_HOST `
+ --build-arg NUGET_USERNAME=$env:NUGET_USERNAME `
+ --build-arg NUGET_PASSWORD=$env:NUGET_PASSWORD `
+ ./
+
if ($LastExitCode -ne 0)
{
throw "error";
};
+ echo "CONTAINER_REGISTRY_HOST=$env:CONTAINER_REGISTRY_HOST" >> $env:GITHUB_ENV;
+
- name: Kubernetes Deploy
shell: pwsh
run: |
- Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
+ Get-Content .kubernetes/service.yaml | foreach { [Environment]::ExpandEnvironmentVariables($_) } | Set-Content .kubernetes/service.tmp.yaml;
kubectl apply -f .kubernetes/service.tmp.yaml;
if ($LastExitCode -ne 0)
{
@@ -156,7 +150,7 @@ jobs:
};
- name: GitHub Release
- if: github.ref == 'refs/heads/master'
+ if: github.ref == 'refs/heads/main'
uses: ncipollo/release-action@v1
with:
tag: v${{ env.VERSION }}
@@ -164,6 +158,8 @@ jobs:
body: |
Version: ${{ env.VERSION }}
Commit: ${{ github.sha }}
+ Build run: ${{ github.run_number }}
+ Image: ${{ env.CONTAINER_REGISTRY_HOST }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
artifacts: "nupkgs/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
diff --git a/Web._Blank/.kubernetes/configmap.yaml b/Web._Blank/.kubernetes/configmap.yaml
index 3977c0ee..d13013d1 100644
--- a/Web._Blank/.kubernetes/configmap.yaml
+++ b/Web._Blank/.kubernetes/configmap.yaml
@@ -1,4 +1,4 @@
- apiVersion: v1
+apiVersion: v1
kind: ConfigMap
metadata:
name: %SERVICE_NAME%-config
diff --git a/Web._Blank/.kubernetes/deployment.yaml b/Web._Blank/.kubernetes/deployment.yaml
index 02882c56..9871912e 100644
--- a/Web._Blank/.kubernetes/deployment.yaml
+++ b/Web._Blank/.kubernetes/deployment.yaml
@@ -73,6 +73,3 @@ spec:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 2
- imagePullSecrets:
- - name: ghcr-pull-secret
-
diff --git a/Web._Blank/Dockerfile b/Web._Blank/Dockerfile
index 119abdb6..7be1dee3 100644
--- a/Web._Blank/Dockerfile
+++ b/Web._Blank/Dockerfile
@@ -29,6 +29,10 @@ RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
+
+RUN mkdir -p /app/wwwroot
+
+ENV ASPNETCORE_HTTP_PORTS=
ENV COMPlus_EnableDiagnostics=0
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
diff --git a/Web._Blank/Web.Blank.Models/Web.Blank.Models.csproj b/Web._Blank/Web.Blank.Models/Web.Blank.Models.csproj
index df35117b..c8a0992a 100644
--- a/Web._Blank/Web.Blank.Models/Web.Blank.Models.csproj
+++ b/Web._Blank/Web.Blank.Models/Web.Blank.Models.csproj
@@ -21,17 +21,11 @@
Michael Vivet
$(ProjectName)
Example project demonstrating a focused aspect of the Nano Library.
-
- A practical example highlighting a specific area or scenario of Nano for learning
- and experimentation. Shows how features or patterns can be applied without
- representing a full application or complete reference.
-
-
- - Added .NET 10 support
-
+ A practical example highlighting a specific area or scenario of Nano for learning and experimentation. Shows how features or patterns can be applied without representing a full application or complete reference.
+
git
- master
- https://github.com/Nano-Core/Nano.Examples.git
+ main
+ https://github.com/Nano-Core/Nano.Lessons.git
$(GitCommitHash)
true
true
@@ -40,7 +34,7 @@
true
$(Version)
nano;example;sample;framework;library;learning;showcase
- https://github.com/Nano-Core/Nano.Library/$(ProjectName)
+ https://github.com/Nano-Core/Nano.Lessons/$(ProjectName)
LICENSE
icon.png
README.md
diff --git a/Web._Blank/Web.Blank/Dockerfile.Local b/Web._Blank/Web.Blank/Dockerfile.Local
index 207af714..ccb45e06 100644
--- a/Web._Blank/Web.Blank/Dockerfile.Local
+++ b/Web._Blank/Web.Blank/Dockerfile.Local
@@ -3,4 +3,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_ASPNET_VERSION AS base
EXPOSE 8080
+ENV ASPNETCORE_HTTP_PORTS=
+
ENTRYPOINT ["dotnet", "Web.Blank.dll"]
\ No newline at end of file