diff --git a/docs/getting-started/1-github-app.md b/docs/getting-started/1-github-app.md index b5b5083..8d29b18 100644 --- a/docs/getting-started/1-github-app.md +++ b/docs/getting-started/1-github-app.md @@ -31,9 +31,10 @@ Make sure to copy the **Secret** set above into your notes for use with AWS Para | Scope | Permission | | -------------- | -------------- | -| Actions | Read-only | +| Actions | Read and write | | Administration | Read-only | | Checks | Read-only | +| Contents | Read and write | | Issues | Read-only | | Metadata | Read-only | | Pull requests | Read and write | diff --git a/docs/getting-started/7-github-actions.md b/docs/getting-started/7-github-actions.md index 716cc10..edcab8c 100644 --- a/docs/getting-started/7-github-actions.md +++ b/docs/getting-started/7-github-actions.md @@ -76,7 +76,7 @@ Actions that apply and retrieve the information needed for builds and deployment ## Notes 1. Labels will be automatically created for each environment in your repository. - 1. Environment labels should be the badge color you want for the environment icon. + 1. Environment label color will be the badge color for the environment icon in comments. 3. In order for a completed or failed deploy status message to show the version, you must provide a `build-details` artifact to your builds that includes a `build-details.json` file with at least the following: 1. The [build-details](/.github/actions/build-details/README.md#build-details-action) action can provide this. diff --git a/prdeploy-api/src/PrDeploy.Api/Auth/GitHubAuthenticationHandler.cs b/prdeploy-api/src/PrDeploy.Api/Auth/GitHubAuthenticationHandler.cs index cef8907..bc12575 100644 --- a/prdeploy-api/src/PrDeploy.Api/Auth/GitHubAuthenticationHandler.cs +++ b/prdeploy-api/src/PrDeploy.Api/Auth/GitHubAuthenticationHandler.cs @@ -44,8 +44,18 @@ protected override async Task HandleAuthenticateAsync() return AuthenticateResult.Fail($"Required claim {JwtRegisteredClaimNames.Name} not present."); } - var encryptedToken = subClaim.Value; - var gitHubToken = _cipherService.Decrypt(encryptedToken); + string gitHubToken; + try + { + var encryptedToken = subClaim.Value; + gitHubToken = _cipherService.Decrypt(encryptedToken); + } + catch + { + // If we are unable to decrypt than it is unauthorized. + return AuthenticateResult.Fail($"Unable to process claim {JwtRegisteredClaimNames.Sub}."); + } + var claims = new List { // This claim is only present locally. diff --git a/prdeploy-api/src/PrDeploy.Api/Filters/SanitizedErrorFilter.cs b/prdeploy-api/src/PrDeploy.Api/Filters/SanitizedErrorFilter.cs index 4074914..66ea536 100644 --- a/prdeploy-api/src/PrDeploy.Api/Filters/SanitizedErrorFilter.cs +++ b/prdeploy-api/src/PrDeploy.Api/Filters/SanitizedErrorFilter.cs @@ -1,4 +1,5 @@ using System.Net; +using FluentValidation; namespace PrDeploy.Api.Filters { @@ -42,6 +43,17 @@ public IError OnError(IError error) } break; + case ValidationException validationException: + var validationMessages = string.Join(", ", validationException.Errors.Select(e => e.ErrorMessage)); + result = ErrorBuilder.FromError(error) + .SetCode("BAD_REQUEST") + .SetMessage(validationMessages) + .SetException( + new HttpRequestException("Bad request.", + null, HttpStatusCode.BadRequest)) + .Build(); + break; + } _logger.LogError(error.Exception, error.Message, error); diff --git a/prdeploy-api/src/PrDeploy.Api/IServiceCollectionExtensions.cs b/prdeploy-api/src/PrDeploy.Api/IServiceCollectionExtensions.cs index 1844b05..f3be690 100644 --- a/prdeploy-api/src/PrDeploy.Api/IServiceCollectionExtensions.cs +++ b/prdeploy-api/src/PrDeploy.Api/IServiceCollectionExtensions.cs @@ -8,6 +8,7 @@ using PrDeploy.Api.Business.Services.Interfaces; using PrDeploy.Api.Filters; using PrDeploy.Api.Business.Auth.Interfaces; +using PrDeploy.Api.Business.Options; using PrDeploy.Api.Schema.Mutations; using PrDeploy.Api.Schema.Queries; @@ -15,7 +16,7 @@ namespace PrDeploy.Api; public static class IServiceCollectionExtensions { - public static IServiceCollection AddPrDeployApi(this IServiceCollection services) + public static IServiceCollection AddPrDeployApi(this IServiceCollection services, IConfiguration configuration) { services .AddGraphQLServer() @@ -62,8 +63,10 @@ public static IServiceCollection AddPrDeployApi(this IServiceCollection services }) .AddScoped(); - - services.AddDataProtection() + var awsOptions = new AwsExtendedOptions(); + configuration.Bind("AWS", awsOptions); + services.AddDataProtection() + .PersistKeysToAWSSystemsManager($"{awsOptions.SecretPathPrefix}/DATA_PROTECTION") .UseCryptographicAlgorithms(new() { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, diff --git a/prdeploy-api/src/PrDeploy.Api/PrDeploy.Api.csproj b/prdeploy-api/src/PrDeploy.Api/PrDeploy.Api.csproj index 5c41a53..ce087b9 100644 --- a/prdeploy-api/src/PrDeploy.Api/PrDeploy.Api.csproj +++ b/prdeploy-api/src/PrDeploy.Api/PrDeploy.Api.csproj @@ -21,6 +21,7 @@ + diff --git a/prdeploy-api/src/PrDeploy.Api/Program.cs b/prdeploy-api/src/PrDeploy.Api/Program.cs index 85c0ead..be0cf31 100644 --- a/prdeploy-api/src/PrDeploy.Api/Program.cs +++ b/prdeploy-api/src/PrDeploy.Api/Program.cs @@ -40,7 +40,7 @@ .CreateBootstrapLogger(); builder.Services - .AddPrDeployApi() + .AddPrDeployApi(configuration) .AddPrDeployApiBusiness(configuration) .AddPrDeployApiModelValidation() .AddGitHubAuthentication( diff --git a/prdeploy-app/src/app/shared/components/header/header.component.ts b/prdeploy-app/src/app/shared/components/header/header.component.ts index e021644..cb6da1d 100644 --- a/prdeploy-app/src/app/shared/components/header/header.component.ts +++ b/prdeploy-app/src/app/shared/components/header/header.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; +import { Component, Input, Output, EventEmitter } from '@angular/core'; import { MatToolbarModule } from '@angular/material/toolbar'; import { UserPanelComponent } from '../user-panel/user-panel.component'; import { RepoManager } from '../../managers'; @@ -17,7 +17,7 @@ import { MatSelectChange, MatSelectModule } from '@angular/material/select'; standalone: true, imports: [MatToolbarModule, MatButtonModule, MatIconModule, MatSelectModule, UserPanelComponent] }) -export class HeaderComponent implements OnInit { +export class HeaderComponent { @Output() menuToggle = new EventEmitter(); @@ -44,9 +44,7 @@ export class HeaderComponent implements OnInit { this.repoManager.ownerReposChanged$ .pipe(takeUntilDestroyed()) .subscribe(ownerRepos => this.updateOwnerRepos(ownerRepos)); - } - ngOnInit(): void { this.fetchOwnerRepos(); } diff --git a/prdeploy-webhooks/src/services/template-service.ts b/prdeploy-webhooks/src/services/template-service.ts index 23569aa..ebcbc7e 100644 --- a/prdeploy-webhooks/src/services/template-service.ts +++ b/prdeploy-webhooks/src/services/template-service.ts @@ -27,6 +27,8 @@ export type TemplateNames = | 'rollback-started.md' | 'services-not-found.md'; +Handlebars.registerHelper('color', hexValue => (hexValue ? hexValue.replace(/^#/, '') : '')); + @scoped(Lifecycle.ContainerScoped) export class TemplateService { private static readonly templates = new Map>(); @@ -56,7 +58,7 @@ export class TemplateService { let p = 0; let positions = '| Position |'; let columns = '|----------|'; - let pulls = `| [${normalizedEnvironment} queue](${prdeployPortalUrl}/{{owner}}/{{repo}}?environment=${normalizedEnvironment}) |`; + let pulls = `| [${normalizedEnvironment} queue](${prdeployPortalUrl}/${owner}/${repo}?environment=${normalizedEnvironment}) |`; for (const pr of queuePullNumbers) { p++; positions += ` ${p} |`; diff --git a/prdeploy-webhooks/templates/deploy-completed.json b/prdeploy-webhooks/templates/deploy-completed.json index ca1a04b..3884302 100644 --- a/prdeploy-webhooks/templates/deploy-completed.json +++ b/prdeploy-webhooks/templates/deploy-completed.json @@ -5,7 +5,7 @@ "elements": [ { "type": "image", - "image_url": "https://via.placeholder.com/32/{{environment.color}}/ffffff?text={{environment.name}}", + "image_url": "https://via.placeholder.com/32/{{color environment.color}}/ffffff?text={{environment.name}}", "alt_text": "{{environment.name}}" }, { diff --git a/prdeploy-webhooks/templates/deploy-completed.md b/prdeploy-webhooks/templates/deploy-completed.md index 12ad6f5..b49a566 100644 --- a/prdeploy-webhooks/templates/deploy-completed.md +++ b/prdeploy-webhooks/templates/deploy-completed.md @@ -1 +1 @@ -{{#if isRollback}}\[ROLLBACK\] {{/if}}[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Deploy%20Complete/{{badge.statusColors.success}}?labelColor={{environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') +{{#if isRollback}}\[ROLLBACK\] {{/if}}[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Deploy%20Complete/{{badge.statusColors.success}}?labelColor={{color environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') diff --git a/prdeploy-webhooks/templates/deploy-failed.md b/prdeploy-webhooks/templates/deploy-failed.md index 4955981..cdd01f4 100644 --- a/prdeploy-webhooks/templates/deploy-failed.md +++ b/prdeploy-webhooks/templates/deploy-failed.md @@ -1,2 +1,2 @@ -{{#if isRollback}}[ROLLBACK] {{/if}}[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Deploy%20Failed/{{badge.statusColors.error}}?labelColor={{environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') +{{#if isRollback}}[ROLLBACK] {{/if}}[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Deploy%20Failed/{{badge.statusColors.error}}?labelColor={{color environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') {{message}} diff --git a/prdeploy-webhooks/templates/deploy-nothing-found.json b/prdeploy-webhooks/templates/deploy-nothing-found.json index 7c1858d..3193ccb 100644 --- a/prdeploy-webhooks/templates/deploy-nothing-found.json +++ b/prdeploy-webhooks/templates/deploy-nothing-found.json @@ -5,7 +5,7 @@ "elements": [ { "type": "image", - "image_url": "https://via.placeholder.com/32/{{environment.color}}/ffffff?text={{environment.name}}", + "image_url": "https://via.placeholder.com/32/{{color environment.color}}/ffffff?text={{environment.name}}", "alt_text": "{{environment.name}}" }, { diff --git a/prdeploy-webhooks/templates/deploy-nothing-found.md b/prdeploy-webhooks/templates/deploy-nothing-found.md index f4b7734..117e178 100644 --- a/prdeploy-webhooks/templates/deploy-nothing-found.md +++ b/prdeploy-webhooks/templates/deploy-nothing-found.md @@ -1,2 +1,2 @@ -![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/No%20Deploys%20Found/{{badge.statusColors.error}}?labelColor={{environment.color}}&icon=github&scale=1.2) +![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/No%20Deploys%20Found/{{badge.statusColors.error}}?labelColor={{color environment.color}}&icon=github&scale=1.2) Nothing found to deploy, make a change to a file in the service you want to include. diff --git a/prdeploy-webhooks/templates/deploy-released.json b/prdeploy-webhooks/templates/deploy-released.json index 6becd1e..6bedefa 100644 --- a/prdeploy-webhooks/templates/deploy-released.json +++ b/prdeploy-webhooks/templates/deploy-released.json @@ -5,7 +5,7 @@ "elements": [ { "type": "image", - "image_url": "https://via.placeholder.com/32/{{environment.color}}/ffffff?text={{environment.name}}", + "image_url": "https://via.placeholder.com/32/{{color environment.color}}/ffffff?text={{environment.name}}", "alt_text": "{{environment.name}}" }, { diff --git a/prdeploy-webhooks/templates/deploy-started.md b/prdeploy-webhooks/templates/deploy-started.md index 37f5b62..8988a15 100644 --- a/prdeploy-webhooks/templates/deploy-started.md +++ b/prdeploy-webhooks/templates/deploy-started.md @@ -1,4 +1,4 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Deploy%20Started/{{badge.statusColors.info}}?labelColor={{environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Deploy%20Started/{{badge.statusColors.info}}?labelColor={{color environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') {{#if environment.requireApproval}} [Approve deployment](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}}) to continue {{/if}} diff --git a/prdeploy-webhooks/templates/environment-approval-required.json b/prdeploy-webhooks/templates/environment-approval-required.json index 90f7661..51f85ba 100644 --- a/prdeploy-webhooks/templates/environment-approval-required.json +++ b/prdeploy-webhooks/templates/environment-approval-required.json @@ -5,7 +5,7 @@ "elements": [ { "type": "image", - "image_url": "https://via.placeholder.com/32/{{environment.color}}/ffffff?text={{environment.name}}", + "image_url": "https://via.placeholder.com/32/{{color environment.color}}/ffffff?text={{environment.name}}", "alt_text": "{{environment.name}}" }, { diff --git a/prdeploy-webhooks/templates/environment-available.json b/prdeploy-webhooks/templates/environment-available.json index be334b3..65e28fd 100644 --- a/prdeploy-webhooks/templates/environment-available.json +++ b/prdeploy-webhooks/templates/environment-available.json @@ -5,7 +5,7 @@ "elements": [ { "type": "image", - "image_url": "https://via.placeholder.com/32/{{environment.color}}/ffffff?text={{environment.name}}", + "image_url": "https://via.placeholder.com/32/{{color environment.color}}/ffffff?text={{environment.name}}", "alt_text": "{{environment.name}}" }, { diff --git a/prdeploy-webhooks/templates/pull-request-checks-incomplete.md b/prdeploy-webhooks/templates/pull-request-checks-incomplete.md index 620ae2b..cfa9fd4 100644 --- a/prdeploy-webhooks/templates/pull-request-checks-incomplete.md +++ b/prdeploy-webhooks/templates/pull-request-checks-incomplete.md @@ -1,4 +1,4 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Checks%20Incomplete/{{badge.statusColors.warn}}?labelColor={{environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Checks%20Incomplete/{{badge.statusColors.warn}}?labelColor={{color environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') The following checks are incomplete: {{#each incompleteChecks}} diff --git a/prdeploy-webhooks/templates/pull-request-checks-redeploy.md b/prdeploy-webhooks/templates/pull-request-checks-redeploy.md index 06b5af0..9494be7 100644 --- a/prdeploy-webhooks/templates/pull-request-checks-redeploy.md +++ b/prdeploy-webhooks/templates/pull-request-checks-redeploy.md @@ -1,2 +1,2 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Check%20Runs%20Complete/{{badge.statusColors.info}}?labelColor={{environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Check%20Runs%20Complete/{{badge.statusColors.info}}?labelColor={{color environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') Triggered a new deployment diff --git a/prdeploy-webhooks/templates/pull-request-enqueued.md b/prdeploy-webhooks/templates/pull-request-enqueued.md index db30691..074cdb3 100644 --- a/prdeploy-webhooks/templates/pull-request-enqueued.md +++ b/prdeploy-webhooks/templates/pull-request-enqueued.md @@ -1,4 +1,4 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/No%20Environment%20Available/{{badge.statusColors.warn}}?labelColor={{environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/No%20Environment%20Available/{{badge.statusColors.warn}}?labelColor={{color environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') {{#if alreadyInQueue}} Your pull request is already in the queue at position {{queuePosition}}. {{else}} diff --git a/prdeploy-webhooks/templates/pull-request-merge-conflicts.json b/prdeploy-webhooks/templates/pull-request-merge-conflicts.json index 7e1dc69..01c78f7 100644 --- a/prdeploy-webhooks/templates/pull-request-merge-conflicts.json +++ b/prdeploy-webhooks/templates/pull-request-merge-conflicts.json @@ -5,7 +5,7 @@ "elements": [ { "type": "image", - "image_url": "https://via.placeholder.com/32/{{environment.color}}/ffffff?text={{environment.name}}", + "image_url": "https://via.placeholder.com/32/{{color environment.color}}/ffffff?text={{environment.name}}", "alt_text": "{{environment.name}}" }, { diff --git a/prdeploy-webhooks/templates/pull-request-merge-conflicts.md b/prdeploy-webhooks/templates/pull-request-merge-conflicts.md index 2645a31..4b55d0a 100644 --- a/prdeploy-webhooks/templates/pull-request-merge-conflicts.md +++ b/prdeploy-webhooks/templates/pull-request-merge-conflicts.md @@ -1,2 +1,2 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Merge%20Conflicts/{{badge.statusColors.error}}?labelColor={{environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Merge%20Conflicts/{{badge.statusColors.error}}?labelColor={{color environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') This branch is out-of-date with the base branch and there are merge conflicts diff --git a/prdeploy-webhooks/templates/pull-request-updated.md b/prdeploy-webhooks/templates/pull-request-updated.md index 6151c62..3820e0e 100644 --- a/prdeploy-webhooks/templates/pull-request-updated.md +++ b/prdeploy-webhooks/templates/pull-request-updated.md @@ -1,2 +1,2 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Branch%20Updated/{{badge.statusColors.warn}}?labelColor={{environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Branch%20Updated/{{badge.statusColors.warn}}?labelColor={{color environment.color}}&icon=github&scale=1.2)]({{prdeployPortalUrl}}/{{owner}}/{{repo}}?environment={{environment.name}} 'Open the queue') {{updateMessage}} diff --git a/prdeploy-webhooks/templates/rollback-completed.md b/prdeploy-webhooks/templates/rollback-completed.md index b8f5335..f241afd 100644 --- a/prdeploy-webhooks/templates/rollback-completed.md +++ b/prdeploy-webhooks/templates/rollback-completed.md @@ -1 +1 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Rollback%20Complete/{{badge.statusColors.success}}?labelColor={{environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Rollback%20Complete/{{badge.statusColors.success}}?labelColor={{color environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') diff --git a/prdeploy-webhooks/templates/rollback-started.md b/prdeploy-webhooks/templates/rollback-started.md index 2fc3a32..63e1c7e 100644 --- a/prdeploy-webhooks/templates/rollback-started.md +++ b/prdeploy-webhooks/templates/rollback-started.md @@ -1,4 +1,4 @@ -[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Rollback%20Started/{{badge.statusColors.warn}}?labelColor={{environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') +[![{{environment.name}}](https://badgen.net/badge/{{environment.name}}/Rollback%20Started/{{badge.statusColors.warn}}?labelColor={{color environment.color}}&icon=github&scale=1.2)](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}} 'Open the deploy') {{#if environment.requireApproval}} [Approve deployment](https://github.com/{{owner}}/{{repo}}/actions/runs/{{run.id}}/attempts/{{run.run_attempt}}) to continue {{/if}}