Skip to content

Commit

Permalink
feat(repo_settings/build): approve build mechanism and related repo s…
Browse files Browse the repository at this point in the history
…ettings (#745)
  • Loading branch information
ecrupper authored Dec 12, 2023
1 parent 370df1a commit 25da227
Show file tree
Hide file tree
Showing 17 changed files with 401 additions and 62 deletions.
27 changes: 27 additions & 0 deletions cypress/fixtures/build_pending_approval.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"id": 15,
"repo_id": 1,
"number": 8,
"parent": 1,
"event": "pull_request",
"status": "pending approval",
"error": "",
"enqueued": 1572980376,
"created": 1572980376,
"started": 1572980375,
"finished": 1572980375,
"deploy": "",
"clone": "https://github.com/github/octocat.git",
"source": "https://github.com/github/octocat/commit/9b1d8bded6e992ab660eaee527c5e3232d0a2441",
"title": "push received from https://github.com/github/octocat",
"message": "fixing docker params",
"commit": "9b1d8bded6e992ab660eaee527c5e3232d0a2441",
"sender": "CookieCat",
"author": "CookieCat",
"branch": "infra",
"ref": "refs/heads/infra",
"base_ref": "",
"host": "",
"runtime": "docker",
"distribution": "linux"
}
3 changes: 2 additions & 1 deletion cypress/fixtures/repository.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
"allow_deploy": false,
"allow_tag": false,
"allow_comment": false,
"pipeline_type": "yaml"
"pipeline_type": "yaml",
"approve_build": "fork-always"
}
3 changes: 2 additions & 1 deletion cypress/fixtures/repository_updated.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
"allow_deploy": true,
"allow_tag": true,
"allow_comment": false,
"pipeline_type": "yaml"
"pipeline_type": "yaml",
"approve_build": "fork-no-write"
}
27 changes: 27 additions & 0 deletions cypress/integration/build.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,33 @@ context('Build', () => {
});
});

context('server stubbed Approve Build', () => {
beforeEach(() => {
cy.visit('/github/octocat/8');
cy.server();
cy.fixture('build_pending_approval.json').as('approveBuild');
cy.route({
method: 'POST',
url: 'api/v1/repos/*/*/builds/*/approve',
status: 200,
response: 'approved build github/octocat/8',
});
cy.get('[data-test=approve-build]').as('approvedBuild');
});

it('there should be a notice banner', () => {
cy.get('[data-test=approve-build-notice').should('exist');
});

it('clicking cancel build should show alert', () => {
cy.get('@approvedBuild').click();
cy.get('[data-test=alert]').should(
'contain',
'approved build github/octocat/8',
);
});
});

context('visit running build', () => {
beforeEach(() => {
cy.visit('/github/octocat/1');
Expand Down
9 changes: 9 additions & 0 deletions cypress/integration/repo_settings.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ context('Repo Settings', () => {
cy.get('@accessRadio').should('have.checked');
});

it('clicking outside contributor approval policy should toggle', () => {
cy.get('[data-test=repo-radio-fork-no-write] input').as(
'forkPolicyRadio',
);
cy.get('@forkPolicyRadio').should('not.have.checked');
cy.get('@forkPolicyRadio').click({ force: true });
cy.get('@forkPolicyRadio').should('have.checked');
});

it('clicking pipeline type radio should toggle all values', () => {
cy.get('[data-test=repo-radio-private] input').as('pipelineTypeRadio');
cy.get('@pipelineTypeRadio').should('not.have.checked');
Expand Down
7 changes: 7 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Cypress.Commands.add('stubBuild', () => {
cy.fixture('build_failure.json').as('failureBuild');
cy.fixture('build_error.json').as('errorBuild');
cy.fixture('build_canceled.json').as('cancelBuild');
cy.fixture('build_pending_approval.json').as('pendingApprovalBuild');
cy.route({
method: 'GET',
url: 'api/v1/repos/*/*/builds/1',
Expand Down Expand Up @@ -105,6 +106,12 @@ Cypress.Commands.add('stubBuild', () => {
status: 200,
response: '@successBuild',
});
cy.route({
method: 'GET',
url: 'api/v1/repos/*/*/builds/8',
status: 200,
response: `@pendingApprovalBuild`,
});
});

Cypress.Commands.add('stubBuilds', () => {
Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ services:
QUEUE_DRIVER: redis
QUEUE_ADDR: 'redis://redis:6379'
QUEUE_PRIVATE_KEY: 'tCIevHOBq6DdN5SSBtteXUusjjd0fOqzk2eyi0DMq04NewmShNKQeUbbp3vkvIckb4pCxc+vxUo+mYf/vzOaSg=='
QUEUE_PUBLIC_KEY: 'DXsJkoTSkHlG26d75LyHJG+KQsXPr8VKPpmH/78zmko='
SCM_DRIVER: github
SCM_CONTEXT: 'continuous-integration/vela'
SECRET_VAULT: 'true'
Expand All @@ -55,7 +56,6 @@ services:
VELA_LOG_LEVEL: trace
# comment the line below to use registration flow
VELA_SECRET: 'zB7mrKDTZqNeNTD8z47yG4DHywspAh'
QUEUE_PUBLIC_KEY: 'DXsJkoTSkHlG26d75LyHJG+KQsXPr8VKPpmH/78zmko='
VELA_SERVER_PRIVATE_KEY: 'F534FF2A080E45F38E05DC70752E6787'
VELA_USER_REFRESH_TOKEN_DURATION: 90m
VELA_USER_ACCESS_TOKEN_DURATION: 60m
Expand Down Expand Up @@ -88,7 +88,6 @@ services:
EXECUTOR_DRIVER: linux
QUEUE_DRIVER: redis
QUEUE_ADDR: 'redis://redis:6379'
QUEUE_PUBLIC_KEY: 'DXsJkoTSkHlG26d75LyHJG+KQsXPr8VKPpmH/78zmko='
VELA_BUILD_LIMIT: 1
VELA_BUILD_TIMEOUT: 30m
VELA_LOG_LEVEL: trace
Expand Down
9 changes: 9 additions & 0 deletions src/elm/Api.elm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Api exposing
, addDeployment
, addSchedule
, addSecret
, approveBuild
, cancelBuild
, chownRepo
, deleteRepo
Expand Down Expand Up @@ -556,6 +557,14 @@ restartBuild model org repository buildNumber =
|> withAuth model.session


{-| approveBuild : approves a build
-}
approveBuild : PartialModel a -> Org -> Repo -> BuildNumber -> Request String
approveBuild model org repository buildNumber =
post model.velaAPI (Endpoint.ApproveBuild org repository buildNumber) Http.emptyBody Json.Decode.string
|> withAuth model.session


{-| cancelBuild : cancels a build
-}
cancelBuild : PartialModel a -> Org -> Repo -> BuildNumber -> Request Build
Expand Down
4 changes: 4 additions & 0 deletions src/elm/Api/Endpoint.elm
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Endpoint
| Builds (Maybe Pagination.Page) (Maybe Pagination.PerPage) (Maybe Event) Org Repo
| Build Org Repo BuildNumber
| CancelBuild Org Repo BuildNumber
| ApproveBuild Org Repo BuildNumber
| Services (Maybe Pagination.Page) (Maybe Pagination.PerPage) Org Repo BuildNumber
| ServiceLogs Org Repo BuildNumber ServiceNumber
| Steps (Maybe Pagination.Page) (Maybe Pagination.PerPage) Org Repo BuildNumber
Expand Down Expand Up @@ -124,6 +125,9 @@ toUrl api endpoint =
CancelBuild org repo buildNumber ->
url api [ "repos", org, repo, "builds", buildNumber, "cancel" ] []

ApproveBuild org repo buildNumber ->
url api [ "repos", org, repo, "builds", buildNumber, "approve" ] []

Services maybePage maybePerPage org repo buildNumber ->
url api [ "repos", org, repo, "builds", buildNumber, "services" ] <| Pagination.toQueryParams maybePage maybePerPage

Expand Down
27 changes: 24 additions & 3 deletions src/elm/Help/Commands.elm
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ commands page =
[ listDeployments org repo ]

Pages.Build org repo buildNumber _ ->
[ viewBuild org repo buildNumber, restartBuild org repo buildNumber, cancelBuild org repo buildNumber, listSteps org repo buildNumber, viewStep org repo buildNumber ]
[ viewBuild org repo buildNumber, approveBuild org repo buildNumber, restartBuild org repo buildNumber, cancelBuild org repo buildNumber, listSteps org repo buildNumber, viewStep org repo buildNumber ]

Pages.BuildServices org repo buildNumber _ ->
[ viewBuild org repo buildNumber, restartBuild org repo buildNumber, cancelBuild org repo buildNumber, listServices org repo buildNumber, viewService org repo buildNumber ]
[ viewBuild org repo buildNumber, approveBuild org repo buildNumber, restartBuild org repo buildNumber, cancelBuild org repo buildNumber, listServices org repo buildNumber, viewService org repo buildNumber ]

Pages.BuildPipeline org repo buildNumber _ _ ->
[ viewBuild org repo buildNumber, restartBuild org repo buildNumber ]
[ viewBuild org repo buildNumber, approveBuild org repo buildNumber, restartBuild org repo buildNumber ]

Pages.BuildGraph org repo buildNumber ->
[ viewBuild org repo buildNumber, restartBuild org repo buildNumber ]
Expand Down Expand Up @@ -255,6 +255,27 @@ viewBuild org repo buildNumber =
Command name content docs noIssue


{-| approveBuild : returns cli command for approving a build
eg.
vela approve build --org octocat --repo hello-world --build 1
-}
approveBuild : Org -> Repo -> BuildNumber -> Command
approveBuild org repo buildNumber =
let
name =
"Approve Build"

content =
Just <| "vela approve build " ++ buildArgs org repo buildNumber

docs =
Just "/build/approve"
in
Command name content docs noIssue


{-| restartBuild : returns cli command for restarting a build
eg.
Expand Down
53 changes: 51 additions & 2 deletions src/elm/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,12 @@ type Msg
| RepairRepo Repository
| UpdateRepoEvent Org Repo Field Bool
| UpdateRepoAccess Org Repo Field String
| UpdateRepoForkPolicy Org Repo Field String
| UpdateRepoPipelineType Org Repo Field String
| UpdateRepoLimit Org Repo Field Int
| UpdateRepoTimeout Org Repo Field Int
| UpdateRepoCounter Org Repo Field Int
| ApproveBuild Org Repo BuildNumber
| RestartBuild Org Repo BuildNumber
| CancelBuild Org Repo BuildNumber
| RedeliverHook Org Repo HookNumber
Expand All @@ -457,6 +459,7 @@ type Msg
| RepoUpdatedResponse Field (Result (Http.Detailed.Error String) ( Http.Metadata, Repository ))
| RepoChownedResponse Repository (Result (Http.Detailed.Error String) ( Http.Metadata, String ))
| RepoRepairedResponse Repository (Result (Http.Detailed.Error String) ( Http.Metadata, String ))
| ApprovedBuildResponse Org Repo BuildNumber (Result (Http.Detailed.Error String) ( Http.Metadata, String ))
| RestartedBuildResponse Org Repo BuildNumber (Result (Http.Detailed.Error String) ( Http.Metadata, Build ))
| CancelBuildResponse Org Repo BuildNumber (Result (Http.Detailed.Error String) ( Http.Metadata, Build ))
| OrgBuildsResponse Org (Result (Http.Detailed.Error String) ( Http.Metadata, Builds ))
Expand Down Expand Up @@ -1223,6 +1226,28 @@ update msg model =
, cmd
)

UpdateRepoForkPolicy org repo field value ->
let
payload : UpdateRepositoryPayload
payload =
buildUpdateRepoStringPayload field value

cmd =
if Pages.RepoSettings.validForkPolicyUpdate rm.repo payload then
let
body : Http.Body
body =
Http.jsonBody <| encodeUpdateRepository payload
in
Api.try (RepoUpdatedResponse field) (Api.updateRepository model org repo body)

else
Cmd.none
in
( model
, cmd
)

UpdateRepoPipelineType org repo field value ->
let
payload : UpdateRepositoryPayload
Expand Down Expand Up @@ -1287,6 +1312,15 @@ update msg model =
, Api.try (RepoUpdatedResponse field) (Api.updateRepository model org repo body)
)

ApproveBuild org repo buildNumber ->
let
newModel =
{ model | buildMenuOpen = [] }
in
( newModel
, approveBuild model org repo buildNumber
)

RestartBuild org repo buildNumber ->
let
newModel =
Expand Down Expand Up @@ -1630,6 +1664,15 @@ update msg model =
Err error ->
( model, addError error )

ApprovedBuildResponse org repo buildNumber response ->
case response of
Ok _ ->
( model, Cmd.none )
|> Alerting.addToastIfUnique Alerts.successConfig AlertsUpdate (Alerts.Success "Success" ("Build approved to run " ++ String.join "/" [ org, repo, buildNumber ]) Nothing)

Err error ->
( model, addError error )

RestartedBuildResponse org repo buildNumber response ->
case response of
Ok ( _, build ) ->
Expand Down Expand Up @@ -4819,7 +4862,7 @@ homeMsgs =
-}
navMsgs : Nav.Msgs Msg
navMsgs =
Nav.Msgs FetchSourceRepositories ToggleFavorite RefreshSettings RefreshHooks RefreshSecrets RestartBuild CancelBuild
Nav.Msgs FetchSourceRepositories ToggleFavorite RefreshSettings RefreshHooks RefreshSecrets ApproveBuild RestartBuild CancelBuild


{-| sourceReposMsgs : prepares the input record required for the SourceRepos page to route Msgs back to Main.elm
Expand All @@ -4833,7 +4876,7 @@ sourceReposMsgs =
-}
repoSettingsMsgs : Pages.RepoSettings.Msgs Msg
repoSettingsMsgs =
Pages.RepoSettings.Msgs UpdateRepoEvent UpdateRepoAccess UpdateRepoLimit ChangeRepoLimit UpdateRepoTimeout ChangeRepoTimeout UpdateRepoCounter ChangeRepoCounter DisableRepo EnableRepo Copy ChownRepo RepairRepo UpdateRepoPipelineType
Pages.RepoSettings.Msgs UpdateRepoEvent UpdateRepoAccess UpdateRepoForkPolicy UpdateRepoLimit ChangeRepoLimit UpdateRepoTimeout ChangeRepoTimeout UpdateRepoCounter ChangeRepoCounter DisableRepo EnableRepo Copy ChownRepo RepairRepo UpdateRepoPipelineType


{-| buildMsgs : prepares the input record required for the Build pages to route Msgs back to Main.elm
Expand All @@ -4846,6 +4889,7 @@ buildMsgs =
, collapseAllServices = CollapseAllServices
, expandAllServices = ExpandAllServices
, expandService = ExpandService
, approveBuild = ApproveBuild
, restartBuild = RestartBuild
, cancelBuild = CancelBuild
, toggle = ShowHideBuildMenu
Expand Down Expand Up @@ -5027,6 +5071,11 @@ getBuildServicesLogs model org repo buildNumber services logFocus refresh =
services


approveBuild : Model -> Org -> Repo -> BuildNumber -> Cmd Msg
approveBuild model org repo buildNumber =
Api.try (ApprovedBuildResponse org repo buildNumber) <| Api.approveBuild model org repo buildNumber


restartBuild : Model -> Org -> Repo -> BuildNumber -> Cmd Msg
restartBuild model org repo buildNumber =
Api.try (RestartedBuildResponse org repo buildNumber) <| Api.restartBuild model org repo buildNumber
Expand Down
Loading

0 comments on commit 25da227

Please sign in to comment.