From fefb223a137c10877cec2df140fe3e86d1632c25 Mon Sep 17 00:00:00 2001 From: Benjamin Michaelis Date: Fri, 20 Sep 2024 14:43:40 -0700 Subject: [PATCH] feat: Add GH Action Template (#449) --- templates/Coalesce.Vue.Template/TestLocal.ps1 | 6 +- .../workflows/build-test-and-deploy.yml | 103 ++++++++++++++++++ .../content/.template.config/template.json | 19 +++- .../Api/Generated/UserController.g.cs | 10 +- .../Models/Generated/UserInfoDto.g.cs | 10 ++ .../package-lock.json | 18 +-- .../Coalesce.Starter.Vue.Web/package.json | 4 +- .../Coalesce.Starter.Vue.Web/src/App.vue | 2 + .../src/metadata.g.ts | 6 + .../Coalesce.Starter.Vue.Web/src/models.g.ts | 1 + .../content/Directory.Build.props | 2 +- .../content/package-lock.json | 6 - 12 files changed, 155 insertions(+), 32 deletions(-) create mode 100644 templates/Coalesce.Vue.Template/content/.github/workflows/build-test-and-deploy.yml delete mode 100644 templates/Coalesce.Vue.Template/content/package-lock.json diff --git a/templates/Coalesce.Vue.Template/TestLocal.ps1 b/templates/Coalesce.Vue.Template/TestLocal.ps1 index 685cdb84e..2dcab9f6f 100644 --- a/templates/Coalesce.Vue.Template/TestLocal.ps1 +++ b/templates/Coalesce.Vue.Template/TestLocal.ps1 @@ -20,7 +20,11 @@ dotnet new coalescevue --help foreach ($testCase in $testCases) { Write-Output "-------TEST CASE------" - Write-Output (!$testCase ? "" : $testCase); + if (-not $testCase) { + Write-Output "" + } else { + Write-Output $testCase + } Write-Output "----------------------" Write-Output "" diff --git a/templates/Coalesce.Vue.Template/content/.github/workflows/build-test-and-deploy.yml b/templates/Coalesce.Vue.Template/content/.github/workflows/build-test-and-deploy.yml new file mode 100644 index 000000000..fde4debd9 --- /dev/null +++ b/templates/Coalesce.Vue.Template/content/.github/workflows/build-test-and-deploy.yml @@ -0,0 +1,103 @@ +name: Build, Test, and Deploy Coalesce.Starter.Vue + +# https://docs.github.com/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +# CONFIGURATION +# For help, go to https://github.com/Azure/Actions +# +# 1. Set up the production Environment in the GitHub Repository Settings. +# Environment Protection Rules are recommended to prevent accidental deployments. +# https://docs.github.com/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#deployment-protection-rules +# +# 2. Set up the following secrets in your repository - https://docs.github.com/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-an-environment +# AZURE_WEBAPP_PUBLISH_PROFILE +# +# 3. Change these variables for your configuration: +env: + AZURE_WEBAPP_NAME: MY_WEBAPP_NAME # set this to your app service name + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + lfs: true + + - name: Use .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + include-preview: true + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + + - name: npm ci + run: npm ci + working-directory: Coalesce.Starter.Vue.Web + + - name: Restore Nuget packages + run: dotnet restore + + - name: Check Coalesce has been run + run: dotnet coalesce --what-if --verify + working-directory: Coalesce.Starter.Vue.Web + + - name: npm run lint + run: npm run lint + working-directory: Coalesce.Starter.Vue.Web + + - name: npm run build + run: npm run build + working-directory: Coalesce.Starter.Vue.Web + + - name: dotnet build + run: dotnet build --configuration Release --no-restore --no-incremental + + - name: dotnet test + run: dotnet test --configuration Release --no-restore --no-build + + - name: dotnet publish + run: dotnet publish ${{ github.workspace }}/Coalesce.Starter.Vue.Web/Coalesce.Starter.Vue.Web.csproj --configuration Release --output ${{ github.workspace }}/publish --no-restore --no-build + + - name: Upload artifact for deployment + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: .coalesce-app + path: ${{ github.workspace }}/publish + if-no-files-found: error + + # Deploys the app to Azure App Service + # https://docs.github.com/actions/use-cases-and-examples/deploying/deploying-net-to-azure-app-service + deploy-production: + needs: build-and-test + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + environment: + name: 'production' + url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} + + steps: + - name: Download artifact for deployment + uses: actions/download-artifact@v4 + with: + name: .coalesce-app + + - name: Deploy to Azure Web App + uses: azure/webapps-deploy@v3 + with: + app-name: ${{ env.AZURE_WEBAPP_NAME }} + slot-name: 'production' + publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }} + package: . diff --git a/templates/Coalesce.Vue.Template/content/.template.config/template.json b/templates/Coalesce.Vue.Template/content/.template.config/template.json index f33f6888c..8b4446e22 100644 --- a/templates/Coalesce.Vue.Template/content/.template.config/template.json +++ b/templates/Coalesce.Vue.Template/content/.template.config/template.json @@ -41,7 +41,7 @@ "datatype": "bool", "displayName": "Sign-in with Microsoft", "description": "Adds Microsoft as an external authentication and account provider for Identity.", - "$coalesceRequires": ["and", "Identity"], + "$coalesceRequires": [ "and", "Identity" ], "$coalesceLink": "https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/microsoft-logins" }, "GoogleAuth": { @@ -49,7 +49,7 @@ "datatype": "bool", "displayName": "Sign-in with Google", "description": "Adds Google as an external authentication and account provider for Identity.", - "$coalesceRequires": ["and", "Identity"], + "$coalesceRequires": [ "and", "Identity" ], "$coalesceLink": "https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins" }, "UserPictures": { @@ -57,7 +57,7 @@ "datatype": "bool", "displayName": "User Profile Pictures", "description": "Adds infrastructure for acquiring, saving, and displaying user profile pictures.", - "$coalesceRequires": ["and", "Identity"] + "$coalesceRequires": [ "and", "Identity" ] }, "TrackingBase": { "type": "parameter", @@ -103,6 +103,13 @@ "displayName": "CI: Azure Pipelines", "description": "Include an azure-pipelines.yml build template. For deployments, a release pipeline is recommended (which don't support YAML config files).", "$coalesceLink": "https://learn.microsoft.com/en-us/azure/devops/pipelines/create-first-pipeline?view=azure-devops&tabs=net%2Cbrowser" + }, + "GithubActions": { + "type": "parameter", + "datatype": "bool", + "displayName": "CI: Github Actions", + "description": "Include an build-test-and-deploy.yml github action file template.", + "$coalesceLink": "https://docs.github.com/actions/use-cases-and-examples/deploying/deploying-net-to-azure-app-service" } }, "sources": [ @@ -167,7 +174,11 @@ }, { "condition": "!AzurePipelines", - "exclude": ["**/azure-pipelines.yml"] + "exclude": [ "**/azure-pipelines.yml" ] + }, + { + "condition": "!GithubActions", + "exclude": [ "**/.github" ] } ] } diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Api/Generated/UserController.g.cs b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Api/Generated/UserController.g.cs index e4fae3e3a..0d51ced8d 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Api/Generated/UserController.g.cs +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Api/Generated/UserController.g.cs @@ -115,15 +115,7 @@ public virtual Task> BulkSave( ); if (_methodResult.Object != null) { - string _contentType = _methodResult.Object.ContentType; - if (string.IsNullOrWhiteSpace(_contentType) && ( - string.IsNullOrWhiteSpace(_methodResult.Object.Name) || - !(new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider().TryGetContentType(_methodResult.Object.Name, out _contentType)) - )) - { - _contentType = "application/octet-stream"; - } - return File(_methodResult.Object.Content, _contentType, _methodResult.Object.Name, !(_methodResult.Object.Content is System.IO.MemoryStream)); + return File(_methodResult.Object); } var _result = new ItemResult(_methodResult); _result.Object = _methodResult.Object; diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Models/Generated/UserInfoDto.g.cs b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Models/Generated/UserInfoDto.g.cs index e58815ac3..013587b28 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Models/Generated/UserInfoDto.g.cs +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/Models/Generated/UserInfoDto.g.cs @@ -14,6 +14,7 @@ public UserInfoParameter() { } private string _Id; private string _UserName; + private string _Email; private string _FullName; private System.Collections.Generic.ICollection _Roles; private System.Collections.Generic.ICollection _Permissions; @@ -28,6 +29,11 @@ public string UserName get => _UserName; set { _UserName = value; Changed(nameof(UserName)); } } + public string Email + { + get => _Email; + set { _Email = value; Changed(nameof(Email)); } + } public string FullName { get => _FullName; @@ -55,6 +61,7 @@ public override void MapTo(Coalesce.Starter.Vue.Data.Auth.UserInfo entity, IMapp if (ShouldMapTo(nameof(Id))) entity.Id = Id; if (ShouldMapTo(nameof(UserName))) entity.UserName = UserName; + if (ShouldMapTo(nameof(Email))) entity.Email = Email; if (ShouldMapTo(nameof(FullName))) entity.FullName = FullName; if (ShouldMapTo(nameof(Roles))) entity.Roles = Roles; if (ShouldMapTo(nameof(Permissions))) entity.Permissions = Permissions; @@ -76,6 +83,7 @@ public override Coalesce.Starter.Vue.Data.Auth.UserInfo MapToNew(IMappingContext if (OnUpdate(entity, context)) return entity; if (ShouldMapTo(nameof(Id))) entity.Id = Id; if (ShouldMapTo(nameof(UserName))) entity.UserName = UserName; + if (ShouldMapTo(nameof(Email))) entity.Email = Email; if (ShouldMapTo(nameof(FullName))) entity.FullName = FullName; return entity; @@ -88,6 +96,7 @@ public UserInfoResponse() { } public string Id { get; set; } public string UserName { get; set; } + public string Email { get; set; } public string FullName { get; set; } public System.Collections.Generic.ICollection Roles { get; set; } public System.Collections.Generic.ICollection Permissions { get; set; } @@ -102,6 +111,7 @@ public override void MapFrom(Coalesce.Starter.Vue.Data.Auth.UserInfo obj, IMappi this.Id = obj.Id; this.UserName = obj.UserName; + this.Email = obj.Email; this.FullName = obj.FullName; this.Roles = obj.Roles; this.Permissions = obj.Permissions; diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package-lock.json b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package-lock.json index 4403d26b5..7288379cf 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package-lock.json +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package-lock.json @@ -10,8 +10,8 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "@vueuse/core": "^11.0.3", - "coalesce-vue": "5.0.0-ci.20240905.3", - "coalesce-vue-vuetify3": "5.0.0-ci.20240905.3", + "coalesce-vue": "5.0.0", + "coalesce-vue-vuetify3": "5.0.0", "typeface-roboto": "1.1.13", "vue": "^3.5.0", "vue-router": "^4.4.3", @@ -1949,9 +1949,9 @@ } }, "node_modules/coalesce-vue": { - "version": "5.0.0-ci.20240905.3", - "resolved": "https://registry.npmjs.org/coalesce-vue/-/coalesce-vue-5.0.0-ci.20240905.3.tgz", - "integrity": "sha512-/yvIvnV5VSoIq3R5kKkSkbg5ERhePA+OSQGbgn/LAwyZP11TPsDrfrar2qD4X9DpbCqD9uYWT9iFO+pAI7lQeA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/coalesce-vue/-/coalesce-vue-5.0.0.tgz", + "integrity": "sha512-9PgBfetmP5XJNwehjk4noU0p8oWdJ8Jl7lnXRezaNQAfhB0Co757+INQlDVipCw8VmYg40IW1zDTKH9E/R5DIA==", "dependencies": { "@types/lodash-es": "^4.17.3", "axios": "^1.3.4", @@ -1969,9 +1969,9 @@ } }, "node_modules/coalesce-vue-vuetify3": { - "version": "5.0.0-ci.20240905.3", - "resolved": "https://registry.npmjs.org/coalesce-vue-vuetify3/-/coalesce-vue-vuetify3-5.0.0-ci.20240905.3.tgz", - "integrity": "sha512-s03t1y23B8uq5RzWwcpUHaCapFQhRpbskWbqIupJMTwmawh/JRqzQROyORorqaHQ17UR1DMaDgS/LUqJPP5Ulg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/coalesce-vue-vuetify3/-/coalesce-vue-vuetify3-5.0.0.tgz", + "integrity": "sha512-RFngKY8/lVgsSoPN1+Y1jdkEKI00sUBrGTArtPX69BpGpvBQxDN+Ctx/kmN90HhlLNwqpF2Sr5gTTSGV4Yc90Q==", "dependencies": { "date-fns": "^3.0.0", "date-fns-tz": "^3.0.0", @@ -1981,7 +1981,7 @@ "vue-router": "^4.4.1" }, "peerDependencies": { - "coalesce-vue": "5.0.0-ci.20240905.3", + "coalesce-vue": "5.0.0", "vue": "^3.4.0", "vuetify": "^3.7.1" } diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package.json b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package.json index faaa819a0..4650a0830 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package.json +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/package.json @@ -15,8 +15,8 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "@vueuse/core": "^11.0.3", - "coalesce-vue": "5.0.0-ci.20240905.3", - "coalesce-vue-vuetify3": "5.0.0-ci.20240905.3", + "coalesce-vue": "5.0.0", + "coalesce-vue-vuetify3": "5.0.0", "typeface-roboto": "1.1.13", "vue": "^3.5.0", "vue-router": "^4.4.3", diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/App.vue b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/App.vue index 954616ce9..8d977b636 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/App.vue +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/App.vue @@ -108,8 +108,10 @@ import { useTheme } from "vuetify"; const drawer = ref(null); +//#if Identity const router = useRouter(); const { userInfo } = useUser(); +//#endif //#if DarkMode const vuetifyTheme = useTheme(); diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/metadata.g.ts b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/metadata.g.ts index a83199f71..4e00a4d7b 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/metadata.g.ts +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/metadata.g.ts @@ -630,6 +630,12 @@ export const UserInfo = domain.types.UserInfo = { type: "string", role: "value", }, + email: { + name: "email", + displayName: "Email", + type: "string", + role: "value", + }, fullName: { name: "fullName", displayName: "Full Name", diff --git a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/models.g.ts b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/models.g.ts index a1a2eeb7e..3494b6b4b 100644 --- a/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/models.g.ts +++ b/templates/Coalesce.Vue.Template/content/Coalesce.Starter.Vue.Web/src/models.g.ts @@ -227,6 +227,7 @@ export class Widget { export interface UserInfo extends Model { id: string | null userName: string | null + email: string | null fullName: string | null roles: string[] | null permissions: string[] | null diff --git a/templates/Coalesce.Vue.Template/content/Directory.Build.props b/templates/Coalesce.Vue.Template/content/Directory.Build.props index 0f2f56b6d..419e91a74 100644 --- a/templates/Coalesce.Vue.Template/content/Directory.Build.props +++ b/templates/Coalesce.Vue.Template/content/Directory.Build.props @@ -8,7 +8,7 @@ true 5.5 - 5.0.0-ci.20240905.3 + 5.0.0 KeepTemplateOnly;AppInsights;OpenAPI;Identity;MicrosoftAuth;GoogleAuth;AuditLogs;UserPictures;TrackingBase;ExampleModel diff --git a/templates/Coalesce.Vue.Template/content/package-lock.json b/templates/Coalesce.Vue.Template/content/package-lock.json deleted file mode 100644 index 519f5328a..000000000 --- a/templates/Coalesce.Vue.Template/content/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "content", - "lockfileVersion": 3, - "requires": true, - "packages": {} -}