From 2525d7b3a4b8db99b5de66819fdb0939af6971cd Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Thu, 16 Nov 2023 16:42:41 +0200 Subject: [PATCH 01/21] Updating Github integration plugin docs --- .../plugins/github/accounts-config-example.md | 3 + .../includes/plugins/github/plugin-config.md | 2 + .../plugins/github-integration/configure.md | 203 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 content/en/plugins/github-integration/configure.md diff --git a/content/en/includes/plugins/github/accounts-config-example.md b/content/en/includes/plugins/github/accounts-config-example.md index cf7609f16a..22d7774274 100644 --- a/content/en/includes/plugins/github/accounts-config-example.md +++ b/content/en/includes/plugins/github/accounts-config-example.md @@ -14,12 +14,14 @@ github: defaultBranch: master githubAppId: 9753 githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: [] - name: SecondAppRepo organization: company-public repository: second-app-repo defaultBranch: main githubAppId: 9753 githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: [] - name: CompanyPrivateOrgAllRepos organization: company-private orgWideInstallation: true @@ -27,4 +29,5 @@ github: defaultBranch: main githubAppId: 1357 githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey + permissions: [] ``` \ No newline at end of file diff --git a/content/en/includes/plugins/github/plugin-config.md b/content/en/includes/plugins/github/plugin-config.md index e555ef0d02..88bc448b80 100644 --- a/content/en/includes/plugins/github/plugin-config.md +++ b/content/en/includes/plugins/github/plugin-config.md @@ -13,6 +13,7 @@ defaultBranch: githubAppId: githubAppPrivateKey: + permissions: [] ``` All fields are required. @@ -35,6 +36,7 @@ All fields are required. defaultBranch: githubAppId: githubAppPrivateKey: + permissions: [] ``` All fields are required. diff --git a/content/en/plugins/github-integration/configure.md b/content/en/plugins/github-integration/configure.md new file mode 100644 index 0000000000..69a1b5e3d9 --- /dev/null +++ b/content/en/plugins/github-integration/configure.md @@ -0,0 +1,203 @@ +--- +title: Configure GitHub Integration plugin Advanced Features +linkTitle: Configure Features +weight: 10 +description: > +Learn how to configure GitHub Integration plugin's advanced features in your Spinnaker or Armory CD instance. +--- + +## Authorization (AuthZ) support for GitHub App accounts + +Fiat is the microservice in Spinnaker responsible for authorization (authz) for the other Spinnaker services. +By default, it is not enabled, so users are able to perform any action in Spinnaker. +When enabled, Fiat will check the user's permissions before allowing the action to proceed. + +GitHub integration plugin supports Fiat authz for GitHub App accounts configured to determine whether a role or group +can perform the following actions: + +- `READ`: A user can view the GitHub App account's configuration and/or use it as a trigger source. +- `WRITE`: A user can use the GitHub App account as the target account for the GitHub integration plugin stages. + +**How this feature works** + +```mermaid +sequenceDiagram + participant user as User + participant gate as Gate + participant orca as Orca + participant igor as Igor + participant fiat as Fiat + participant gh as GitHub + +user ->> gate: Start execution for pipeline (includes plugin stage) +gate ->> orca: Submit execution for pipeline (includes plugin stage) +orca ->> igor: Submit the task operations of plugin stage +igor ->> fiat: Check hasPermissions +alt Unauthorized + fiat ->> igor: hasPermissions=false + igor ->> orca: Fail with Forbidden + orca ->> gate: TERMINAL +else Authorized + fiat ->> igor: hasPermissions=true + igor ->> orca: IN_PROGRESS + igor ->> gh: API calls + orca ->> gate: IN_PROGRESS +end +``` + +**Pre-requisites** + +- You are familiar with how Spinnaker's [AuthZ](https://docs.armory.io/continuous-deployment/overview/fiat-permissions-overview/) works. +- You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/_index.md" >}}). +- You have enabled Fiat micorservice in your Spinnaker or Armory CD instance integrated with an external identity provider (IDP). + +**How to enable** + +AuthZ support can be enabled per GitHub App account by setting the `permissions` block in the `github-integration-plugin.yml` file. +```yaml +github: + plugin: + accounts: + - name: FirstAppRepo + organization: company-public + repository: first-app-repo + defaultBranch: master + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: + READ: + - "read-only-role" + - "dev-role" + - "ops-role" + EXECUTE: + - "dev-role" + - "ops-role" + - name: SecondAppRepo + organization: company-public + repository: second-app-repo + defaultBranch: main + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: [] + - name: CompanyPrivateOrgAllRepos + organization: company-private + orgWideInstallation: true + includePublicRepositories: false + defaultBranch: main + githubAppId: 1357 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey + permissions: + READ: + - "read-only-role" + - "ops-role" + EXECUTE: + - "ops-role" +``` + +## Validate GitHub access based on GitHub App account assigned configuration +Using the `impersonateGitHubTeam` feature in the GitHub Integration plugin, GitHub App accounts access to repositories +can be validated and enforced based on the GitHub team's assigned configuration. + +**How this feature works** + +GitHub integration plugin will validate before performing any action in a pipeline stage that the GitHub Teams configured +using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: +- `Admin`: Full access to the repository +- `Write`: Read and write access to the repository +- `Maintain`: Read and write access to the repository, including managing issues and pull requests + +If the GitHub team does not have appropriate access to the repository, the pipeline stage will fail with an error message. + +```mermaid +sequenceDiagram + participant user as User + participant gate as Gate + participant orca as Orca + participant igor as Igor + participant fiat as Fiat + participant gh as GitHub + +user ->> gate: Start execution for pipeline (includes plugin stage) +gate ->> orca: Submit execution for pipeline (includes plugin stage) +orca ->> igor: Submit the task operations of plugin stage +igor ->> fiat: Check hasPermissions +alt Unauthorized + fiat ->> igor: hasPermissions=false + igor ->> orca: Fail with Forbidden + orca ->> gate: TERMINAL +else Authorized + fiat ->> igor: hasPermissions=true + igor ->> gh: Check permissions on Repository + gh ->> igor: Permissions + igor ->> igor: Evaluate Repo permissions + alt Unauthorized_onRepo + igor ->> orca: Fail with Forbidden on Repo Access + else Authorized_onRepo + orca ->> gate: IN_PROGRESS + end +end +``` + +**How to enable** +`impersonateGitHubTeam` feature can be enabled per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. +```yaml +github: + plugin: + accounts: + - name: FirstAppRepo + organization: company-public + repository: first-app-repo + defaultBranch: master + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: + READ: + - "read-only-role" + - "dev-role" + - "ops-role" + EXECUTE: + - "dev-role" + - "ops-role" + impersonateGitHubTeam: [] + - name: SecondAppRepo + organization: company-public + repository: second-app-repo + defaultBranch: main + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: [] + impersonateGitHubTeam: + - "dev-github-team" + - "ops-github-team" + - name: CompanyPrivateOrgAllRepos + organization: company-private + orgWideInstallation: true + includePublicRepositories: false + defaultBranch: main + githubAppId: 1357 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey + impersonateGitHubTeam: + - "admin-github-team" + permissions: + READ: + - "read-only-role" + - "ops-role" + EXECUTE: + - "ops-role" +``` + +## Configure GitHub Commit Status Echo notifications + +**How this feature works** + +**How to enable** + +**Migrating from Spinnaker's default implementation** + +## GitHub Commit Status pipeline Stage + +**How this feature works** + +**How to enable** + +**Migrating from a Orca preconfigure webhook implementation** \ No newline at end of file From fe1511af2e8ef02bbeae6eb841b8950878d7aab0 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Thu, 16 Nov 2023 16:58:15 +0200 Subject: [PATCH 02/21] Fixing yaml --- content/en/plugins/github-integration/configure.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/content/en/plugins/github-integration/configure.md b/content/en/plugins/github-integration/configure.md index 69a1b5e3d9..25a79fa2c4 100644 --- a/content/en/plugins/github-integration/configure.md +++ b/content/en/plugins/github-integration/configure.md @@ -5,6 +5,7 @@ weight: 10 description: > Learn how to configure GitHub Integration plugin's advanced features in your Spinnaker or Armory CD instance. --- +![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) ## Authorization (AuthZ) support for GitHub App accounts @@ -54,6 +55,7 @@ end **How to enable** AuthZ support can be enabled per GitHub App account by setting the `permissions` block in the `github-integration-plugin.yml` file. + ```yaml github: plugin: @@ -140,6 +142,7 @@ end **How to enable** `impersonateGitHubTeam` feature can be enabled per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. + ```yaml github: plugin: From f681180650d235ef7370d2c8b1e15ec92a7225db Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Thu, 16 Nov 2023 17:02:23 +0200 Subject: [PATCH 03/21] Trying to fix build issue --- content/en/plugins/github-integration/configure.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/en/plugins/github-integration/configure.md b/content/en/plugins/github-integration/configure.md index 25a79fa2c4..8410016120 100644 --- a/content/en/plugins/github-integration/configure.md +++ b/content/en/plugins/github-integration/configure.md @@ -1,10 +1,11 @@ --- title: Configure GitHub Integration plugin Advanced Features -linkTitle: Configure Features +linkTitle: GitHub Integration weight: 10 description: > -Learn how to configure GitHub Integration plugin's advanced features in your Spinnaker or Armory CD instance. + Learn how to configure GitHub Integration plugin's advanced features in your Spinnaker or Armory CD instance. --- + ![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) ## Authorization (AuthZ) support for GitHub App accounts From 366e7d7ff557ae61d98df1a33ad7ad5f839ad71c Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Thu, 16 Nov 2023 17:12:33 +0200 Subject: [PATCH 04/21] Updating docs --- content/en/plugins/github-integration/configure.md | 8 +++++--- content/en/plugins/github-integration/use.md | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/content/en/plugins/github-integration/configure.md b/content/en/plugins/github-integration/configure.md index 8410016120..b82030e1ca 100644 --- a/content/en/plugins/github-integration/configure.md +++ b/content/en/plugins/github-integration/configure.md @@ -1,9 +1,9 @@ --- -title: Configure GitHub Integration plugin Advanced Features -linkTitle: GitHub Integration +title: Configure GitHub Integration plugin advanced Features +linkTitle: Advanced Features weight: 10 description: > - Learn how to configure GitHub Integration plugin's advanced features in your Spinnaker or Armory CD instance. + Learn how to configure GitHub Integration plugin's advanced features. --- ![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) @@ -98,6 +98,7 @@ github: ``` ## Validate GitHub access based on GitHub App account assigned configuration + Using the `impersonateGitHubTeam` feature in the GitHub Integration plugin, GitHub App accounts access to repositories can be validated and enforced based on the GitHub team's assigned configuration. @@ -142,6 +143,7 @@ end ``` **How to enable** + `impersonateGitHubTeam` feature can be enabled per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. ```yaml diff --git a/content/en/plugins/github-integration/use.md b/content/en/plugins/github-integration/use.md index 02fc98badc..f2ccf501d7 100644 --- a/content/en/plugins/github-integration/use.md +++ b/content/en/plugins/github-integration/use.md @@ -1,6 +1,6 @@ --- title: Use the GitHub Integration Plugin -linkTitle: Use +linkTitle: Use GitHub Integration plugin weight: 5 description: > Learn how to use the GitHub Integration Plugin to trigger Spinnaker pipelines from GitHub and also to trigger GitHub workflows from Spinnaker pipelines. From 64a2adccf460abdbc4eef693a10c172ea0617d57 Mon Sep 17 00:00:00 2001 From: Aimee Ukasick Date: Thu, 16 Nov 2023 13:04:18 -0600 Subject: [PATCH 05/21] move configure to Get Started section; style guide updates --- .../{ => install}/configure.md | 70 +++++++++---------- content/en/plugins/github-integration/use.md | 4 +- 2 files changed, 37 insertions(+), 37 deletions(-) rename content/en/plugins/github-integration/{ => install}/configure.md (68%) diff --git a/content/en/plugins/github-integration/configure.md b/content/en/plugins/github-integration/install/configure.md similarity index 68% rename from content/en/plugins/github-integration/configure.md rename to content/en/plugins/github-integration/install/configure.md index b82030e1ca..4f4ef87543 100644 --- a/content/en/plugins/github-integration/configure.md +++ b/content/en/plugins/github-integration/install/configure.md @@ -1,26 +1,25 @@ --- -title: Configure GitHub Integration plugin advanced Features -linkTitle: Advanced Features +title: Configure GitHub Integration Features +linkTitle: Configure Features weight: 10 description: > - Learn how to configure GitHub Integration plugin's advanced features. + Learn how to configure advanced GitHub Integration features in your Spinnaker or Armory CD instance. --- ![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) -## Authorization (AuthZ) support for GitHub App accounts +## Authorization (AuthZ) -Fiat is the microservice in Spinnaker responsible for authorization (authz) for the other Spinnaker services. -By default, it is not enabled, so users are able to perform any action in Spinnaker. -When enabled, Fiat will check the user's permissions before allowing the action to proceed. +This feature enables AuthZ support for GitHub App accounts. -GitHub integration plugin supports Fiat authz for GitHub App accounts configured to determine whether a role or group -can perform the following actions: +Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. + +The GitHub Integration plugin supports Fiat authz for GitHub App accounts configured to determine whether a role or group can perform the following actions: - `READ`: A user can view the GitHub App account's configuration and/or use it as a trigger source. - `WRITE`: A user can use the GitHub App account as the target account for the GitHub integration plugin stages. -**How this feature works** +### How this feature works ```mermaid sequenceDiagram @@ -47,17 +46,17 @@ else Authorized end ``` -**Pre-requisites** +### {{% heading "prereq" %}} -- You are familiar with how Spinnaker's [AuthZ](https://docs.armory.io/continuous-deployment/overview/fiat-permissions-overview/) works. +- You are familiar with how Spinnaker's [AuthZ]({{< ref "continuous-deployment/overview/fiat-permissions-overview" >}}) works. - You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/_index.md" >}}). -- You have enabled Fiat micorservice in your Spinnaker or Armory CD instance integrated with an external identity provider (IDP). +- You have enabled Fiat in your Spinnaker or Armory CD instance integrated with an external identity provider (IDP). -**How to enable** +### How to enable AuthZ support -AuthZ support can be enabled per GitHub App account by setting the `permissions` block in the `github-integration-plugin.yml` file. +You can enable AuthZ support per GitHub App account by setting the `permissions` block in the `github-integration-plugin.yml` file. For example: -```yaml +{{< highlight yaml "linenos=table,hl_lines=10-17 32-37" >}} github: plugin: accounts: @@ -95,22 +94,23 @@ github: - "ops-role" EXECUTE: - "ops-role" -``` +{{< /highlight >}} + +## Validate GitHub access -## Validate GitHub access based on GitHub App account assigned configuration +This feature validates GitHub access based on configuration assigned to a GitHub App account. -Using the `impersonateGitHubTeam` feature in the GitHub Integration plugin, GitHub App accounts access to repositories -can be validated and enforced based on the GitHub team's assigned configuration. +Using the `impersonateGitHubTeam` feature, you can validate and enforce GitHub App account access to repositories based on the GitHub team's assigned configuration. -**How this feature works** +### How this feature works + +Before performing any action in a pipeline stage, the plugin validates that the GitHub teams configured using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: -GitHub integration plugin will validate before performing any action in a pipeline stage that the GitHub Teams configured -using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: - `Admin`: Full access to the repository - `Write`: Read and write access to the repository - `Maintain`: Read and write access to the repository, including managing issues and pull requests -If the GitHub team does not have appropriate access to the repository, the pipeline stage will fail with an error message. +If the GitHub team does not have appropriate access to the repository, the pipeline stage fails with an error message. ```mermaid sequenceDiagram @@ -142,11 +142,11 @@ else Authorized end ``` -**How to enable** +### How to enable -`impersonateGitHubTeam` feature can be enabled per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. +You enable the `impersonateGitHubTeam` feature per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. For example: -```yaml +{{< highlight yaml "linenos=table,hl_lines=26-28 36-37" >}} github: plugin: accounts: @@ -190,20 +190,20 @@ github: - "ops-role" EXECUTE: - "ops-role" -``` +{{< /highlight >}} ## Configure GitHub Commit Status Echo notifications -**How this feature works** +### How this feature works -**How to enable** +### How to enable -**Migrating from Spinnaker's default implementation** +### Migrate from Spinnaker's default implementation -## GitHub Commit Status pipeline Stage +## GitHub Commit Status pipeline stage -**How this feature works** +### How this feature works -**How to enable** +### How to enable -**Migrating from a Orca preconfigure webhook implementation** \ No newline at end of file +### Migrate from a Orca preconfigured webhook implementation \ No newline at end of file diff --git a/content/en/plugins/github-integration/use.md b/content/en/plugins/github-integration/use.md index f2ccf501d7..01468f291f 100644 --- a/content/en/plugins/github-integration/use.md +++ b/content/en/plugins/github-integration/use.md @@ -1,9 +1,9 @@ --- title: Use the GitHub Integration Plugin -linkTitle: Use GitHub Integration plugin +linkTitle: How to Use weight: 5 description: > - Learn how to use the GitHub Integration Plugin to trigger Spinnaker pipelines from GitHub and also to trigger GitHub workflows from Spinnaker pipelines. + Learn how to use the GitHub Integration plugin to trigger Spinnaker pipelines from GitHub and also to trigger GitHub workflows from Spinnaker pipelines. --- ## {{% heading "prereq" %}} From d946c6ee43817dc161363c4185483052bb410667 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 13:48:38 +0200 Subject: [PATCH 06/21] Updating Github Commit status --- .../github-integration/install/configure.md | 81 ++++++++++++++++-- static/images/plugins/github/commitStatus.png | Bin 0 -> 118155 bytes 2 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 static/images/plugins/github/commitStatus.png diff --git a/content/en/plugins/github-integration/install/configure.md b/content/en/plugins/github-integration/install/configure.md index 4f4ef87543..addb57969c 100644 --- a/content/en/plugins/github-integration/install/configure.md +++ b/content/en/plugins/github-integration/install/configure.md @@ -14,12 +14,13 @@ This feature enables AuthZ support for GitHub App accounts. Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. +### How this feature works + The GitHub Integration plugin supports Fiat authz for GitHub App accounts configured to determine whether a role or group can perform the following actions: - `READ`: A user can view the GitHub App account's configuration and/or use it as a trigger source. - `WRITE`: A user can use the GitHub App account as the target account for the GitHub integration plugin stages. -### How this feature works ```mermaid sequenceDiagram @@ -193,17 +194,87 @@ github: {{< /highlight >}} ## Configure GitHub Commit Status Echo notifications +Echo is the microservice in Spinnaker which (among other functionalities) manages notifications for Spinnaker pipelines and stages. +Using the GitHub Integration plugin you can configure Echo to create [GitHub Commit Statuses](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) +in a repository by authenticating using the GitHub App accounts configured in the plugin. ### How this feature works +GitHub Integration plugin offers an enhanced Echo notification type which can be configured to send notifications +for pipelines and/or stages statuses with custom context and description linking to the Spinnaker UI as a target URL. + ### How to enable -### Migrate from Spinnaker's default implementation +GitHub Commit Status notifications can be enabled per GitHub App account by enabling the feature in Echo and Deck services +in the `github-integration-plugin.yml` file. + +{{< highlight yaml "linenos=table,hl_lines=7-8 14-15" >}} +spec: + spinnakerConfig: + profiles: + spinnaker: + github: + plugin: + github-status: + enabled: true + accounts: [] + deck: + settings-local.js: | + window.spinnakerSettings = { + ... (content omitted for brevity) + feature.githubIntegrationFlags = { + github-status: true, + ... (content omitted for brevity) + } +{{< /highlight >}} + +### Migrating from Echo's default implementation + +Migrating from the default implementation to the GitHub Integration plugin's implementation does not require any changes in your pipelines. +The GitHub Integration plugin's implementation will be used automatically when the feature is enabled in Echo and Deck services and the default +implementation is disabled. To ensure a smooth migration, follow these steps: + + +1. Disable the default implementation by disabling the `github-status` feature in Echo and Deck services: +{{< highlight yaml "linenos=table,hl_lines=6 13" >}} +spec: + spinnakerConfig: + profiles: + echo: + github-status: + enabled: false + token: + endpoint: https://api.github.com + deck: + settings-local.js: | + window.spinnakerSettings = { + ... (content omitted for brevity) + notifications.githubStatus.enabled = false; + ... (content omitted for brevity) + } +{{< /highlight >}} +2. Enable the GitHub Integration plugin's implementation as described in the previous section. + +3. Ensure that you have configured the appropriate GitHub App accounts for every GitHub organisation that you want to +send notifications to as described in the [GitHub App accounts configuration](#github-app-accounts-configuration) section. + +4. Verify that the Deck UI is showing the plugin's Commit Status notification type in the notification settings for +your pipelines and the Commit Statuses are being created in GitHub. + ## GitHub Commit Status pipeline stage -### How this feature works +The GitHub Commit Status pipeline stage allows you to create a GitHub Commit Status in a repository using the GitHub App +accounts configured in the plugin without the need to configure a notification block in your pipelines and viewing the execution +status of the stage in your pipeline's execution details. -### How to enable +Configure the **Github Integration Commit Status Stage** as in the following screenshot: + +{{< figure src="/images/plugins/github/commitStatus.png" >}} + +* **GitHub Repo**: (Required) The full repository name including the GitHub Org. For example myorg/mygithubrepo. +* **Commit Ref**: (Required) The commit reference. Can be a commit SHA, branch name (heads/BRANCH_NAME), or tag name (tags/TAG_NAME). +* **Status**: (Required) The state of the status. Can be one of: error, failure, pending, success. +* **Context**: (Required) A string label to differentiate this status from the status of other systems. This field is case-insensitive. +* **Description**: (Optional) A short description of the status. -### Migrate from a Orca preconfigured webhook implementation \ No newline at end of file diff --git a/static/images/plugins/github/commitStatus.png b/static/images/plugins/github/commitStatus.png new file mode 100644 index 0000000000000000000000000000000000000000..40477adf417d28ccafc17210b1932acf6dc14068 GIT binary patch literal 118155 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 Date: Tue, 21 Nov 2023 14:05:07 +0200 Subject: [PATCH 07/21] Moving Github Commit status stage to Use --- .../github-integration/install/configure.md | 18 ------------------ content/en/plugins/github-integration/use.md | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/content/en/plugins/github-integration/install/configure.md b/content/en/plugins/github-integration/install/configure.md index addb57969c..ad4458473d 100644 --- a/content/en/plugins/github-integration/install/configure.md +++ b/content/en/plugins/github-integration/install/configure.md @@ -260,21 +260,3 @@ send notifications to as described in the [GitHub App accounts configuration](#g 4. Verify that the Deck UI is showing the plugin's Commit Status notification type in the notification settings for your pipelines and the Commit Statuses are being created in GitHub. - - -## GitHub Commit Status pipeline stage - -The GitHub Commit Status pipeline stage allows you to create a GitHub Commit Status in a repository using the GitHub App -accounts configured in the plugin without the need to configure a notification block in your pipelines and viewing the execution -status of the stage in your pipeline's execution details. - -Configure the **Github Integration Commit Status Stage** as in the following screenshot: - -{{< figure src="/images/plugins/github/commitStatus.png" >}} - -* **GitHub Repo**: (Required) The full repository name including the GitHub Org. For example myorg/mygithubrepo. -* **Commit Ref**: (Required) The commit reference. Can be a commit SHA, branch name (heads/BRANCH_NAME), or tag name (tags/TAG_NAME). -* **Status**: (Required) The state of the status. Can be one of: error, failure, pending, success. -* **Context**: (Required) A string label to differentiate this status from the status of other systems. This field is case-insensitive. -* **Description**: (Optional) A short description of the status. - diff --git a/content/en/plugins/github-integration/use.md b/content/en/plugins/github-integration/use.md index 01468f291f..4c1f599a20 100644 --- a/content/en/plugins/github-integration/use.md +++ b/content/en/plugins/github-integration/use.md @@ -95,3 +95,21 @@ You can use the **GitHub Integration Releases Get Details** stage to fetch the l * **Retrieve**: (Required) Select **Get Latest PreRelease** * **Organization or User**: (Required) The organization or username that should trigger the workflow * **Project**: (Required) Spinnaker project name + +## Create GitHub Commit Status + +The GitHub Commit Status pipeline stage allows you to create a GitHub Commit Status in a repository using the GitHub App +accounts configured in the plugin without the need to configure a notification block in your pipelines and viewing the execution +status of the stage in your pipeline's execution details. + +Configure the **Github Integration Commit Status Stage** as in the following screenshot: + +{{< figure src="/images/plugins/github/commitStatus.png" >}} + +* **GitHub Repo**: (Required) The full repository name including the GitHub Org. For example myorg/mygithubrepo. +* **Commit Ref**: (Required) The commit reference. Can be a commit SHA, branch name (heads/BRANCH_NAME), or tag name (tags/TAG_NAME). +* **Status**: (Required) The state of the status. Can be one of: error, failure, pending, success. +* **Context**: (Required) A string label to differentiate this status from the status of other systems. This field is case-insensitive. +* **Description**: (Optional) A short description of the status. + + From ae3e2ceab262608a18a4fd328b57230b28734a41 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:16:03 +0200 Subject: [PATCH 08/21] Updating Github to GitHub --- content/en/plugins/github-integration/use.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/use.md b/content/en/plugins/github-integration/use.md index 4c1f599a20..9b8f9f5f0d 100644 --- a/content/en/plugins/github-integration/use.md +++ b/content/en/plugins/github-integration/use.md @@ -102,7 +102,7 @@ The GitHub Commit Status pipeline stage allows you to create a GitHub Commit Sta accounts configured in the plugin without the need to configure a notification block in your pipelines and viewing the execution status of the stage in your pipeline's execution details. -Configure the **Github Integration Commit Status Stage** as in the following screenshot: +Configure the **GitHub Integration Commit Status Stage** as in the following screenshot: {{< figure src="/images/plugins/github/commitStatus.png" >}} From 5dbacbc00837cf60058c0eab76f8d2a15c939b05 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:23:41 +0200 Subject: [PATCH 09/21] Adding release notes --- content/en/plugins/github-integration/release-notes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index fa996b097d..b8c6732775 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -6,6 +6,11 @@ description: > Github Integration Plugin for Spinnaker release notes. --- +## v0.2.4 2023/11/21 +### Features +- Added support for AuthZ for GitHub App accounts. See [Configure AuthZ](/docs/plugins/github-integration/install/configure/#configure-authz) for more information. +- Added support for Validating GitHub App accounts access. See [Validate GitHub access](/docs/plugins/github-integration/install/configure/#validate-github-access) for more information. + ## v0.1.2 2023/11/01 ### Features From af2dac9ce0d9ed87a8ec511e8598cd6548fb3e59 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:24:43 +0200 Subject: [PATCH 10/21] Fixing link --- content/en/plugins/github-integration/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index b8c6732775..3143596030 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -8,7 +8,7 @@ description: > ## v0.2.4 2023/11/21 ### Features -- Added support for AuthZ for GitHub App accounts. See [Configure AuthZ](/docs/plugins/github-integration/install/configure/#configure-authz) for more information. +- Added support for AuthZ for GitHub App accounts. See [Configure AuthZ](/docs/plugins/github-integration/install/configure/#authorization-authz) for more information. - Added support for Validating GitHub App accounts access. See [Validate GitHub access](/docs/plugins/github-integration/install/configure/#validate-github-access) for more information. ## v0.1.2 2023/11/01 From 534fe97dba057dd78305a8599f28bd1611b20a57 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:31:20 +0200 Subject: [PATCH 11/21] Updating links --- content/en/plugins/github-integration/release-notes.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index 3143596030..bfdd13c65f 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -5,11 +5,10 @@ weight: 99 description: > Github Integration Plugin for Spinnaker release notes. --- - ## v0.2.4 2023/11/21 ### Features -- Added support for AuthZ for GitHub App accounts. See [Configure AuthZ](/docs/plugins/github-integration/install/configure/#authorization-authz) for more information. -- Added support for Validating GitHub App accounts access. See [Validate GitHub access](/docs/plugins/github-integration/install/configure/#validate-github-access) for more information. +- Added support for AuthZ for GitHub App accounts. See [Configure AuthZ](install/configure.md/#authorization-authz) for more information. +- Added support for Validating GitHub App accounts access. See [Validate GitHub access](install/configure.md/#validate-github-access) for more information. ## v0.1.2 2023/11/01 From 98db1e83a666eb0889b6d22730ecfb579024f832 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:39:28 +0200 Subject: [PATCH 12/21] Updating link --- content/en/plugins/github-integration/release-notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index bfdd13c65f..ae7e3ecfee 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -7,8 +7,8 @@ description: > --- ## v0.2.4 2023/11/21 ### Features -- Added support for AuthZ for GitHub App accounts. See [Configure AuthZ](install/configure.md/#authorization-authz) for more information. -- Added support for Validating GitHub App accounts access. See [Validate GitHub access](install/configure.md/#validate-github-access) for more information. +- Added support for AuthZ for GitHub App accounts. See [Authorization (AuthZ)](/docscontent/en/plugins/github-integration/install/configure.md#authorization-authz) for more information. +- Added support for Validating GitHub App accounts access. ## v0.1.2 2023/11/01 From 964dc10699c214a6d4c6dcb391e5621ba24310ad Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:42:16 +0200 Subject: [PATCH 13/21] Updating link --- content/en/plugins/github-integration/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index ae7e3ecfee..cab51326f9 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -7,7 +7,7 @@ description: > --- ## v0.2.4 2023/11/21 ### Features -- Added support for AuthZ for GitHub App accounts. See [Authorization (AuthZ)](/docscontent/en/plugins/github-integration/install/configure.md#authorization-authz) for more information. +- Added support for AuthZ for GitHub App accounts. See [Authorization (AuthZ)](/plugins/github-integration/install/configure/#authorization-authz) for more information. - Added support for Validating GitHub App accounts access. ## v0.1.2 2023/11/01 From 72d8ac5f91950dc3ff01edde16148a17480bbf62 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 14:50:55 +0200 Subject: [PATCH 14/21] Updating with v0.3.1 release --- content/en/plugins/github-integration/release-notes.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index cab51326f9..42f9e0c2f9 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -5,10 +5,15 @@ weight: 99 description: > Github Integration Plugin for Spinnaker release notes. --- +## v0.3.1 2023/12/21 +### Features +- Added support for GitHub Commit Statuses notifications for pipelines and/or stages using Echo service. See [Configure GitHub Commit Status Echo notifications](/plugins/github-integration/install/configure/#configure-github-commit-status-echo-notifications) for more information. +- Added GitHub Commit Status stage for pipelines. See [GitHub Commit Status stage](/plugins/github-integration/use/github-commit-status-stage/) for more information. + ## v0.2.4 2023/11/21 ### Features - Added support for AuthZ for GitHub App accounts. See [Authorization (AuthZ)](/plugins/github-integration/install/configure/#authorization-authz) for more information. -- Added support for Validating GitHub App accounts access. +- Added support for Validating GitHub App accounts access. See [Validating GitHub App accounts access](/plugins/github-integration/install/configure/#validate-github-access) for more information. ## v0.1.2 2023/11/01 From 8619bc93b07ede78331ec0be5d4294d14260ff36 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 15:34:46 +0200 Subject: [PATCH 15/21] Updating docs --- content/en/plugins/github-integration/install/configure.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/install/configure.md b/content/en/plugins/github-integration/install/configure.md index ad4458473d..ee642b8b3a 100644 --- a/content/en/plugins/github-integration/install/configure.md +++ b/content/en/plugins/github-integration/install/configure.md @@ -223,7 +223,8 @@ spec: window.spinnakerSettings = { ... (content omitted for brevity) feature.githubIntegrationFlags = { - github-status: true, + githubStatus: true + }; ... (content omitted for brevity) } {{< /highlight >}} From f2502ef7e774605b5104d40058dbfe242deb943c Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 15:41:28 +0200 Subject: [PATCH 16/21] Updating link --- content/en/plugins/github-integration/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index 42f9e0c2f9..155c2fa581 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -8,7 +8,7 @@ description: > ## v0.3.1 2023/12/21 ### Features - Added support for GitHub Commit Statuses notifications for pipelines and/or stages using Echo service. See [Configure GitHub Commit Status Echo notifications](/plugins/github-integration/install/configure/#configure-github-commit-status-echo-notifications) for more information. -- Added GitHub Commit Status stage for pipelines. See [GitHub Commit Status stage](/plugins/github-integration/use/github-commit-status-stage/) for more information. +- Added GitHub Commit Status stage for pipelines. See [Create GitHub Commit Status](/plugins/github-integration/use/#create-github-commit-status) for more information. ## v0.2.4 2023/11/21 ### Features From 246b32d13e76e8e9151c677ea6d8a1fc45fbeec9 Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Tue, 21 Nov 2023 15:42:03 +0200 Subject: [PATCH 17/21] Updating link --- content/en/plugins/github-integration/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/plugins/github-integration/release-notes.md b/content/en/plugins/github-integration/release-notes.md index 155c2fa581..1ff6b2d628 100644 --- a/content/en/plugins/github-integration/release-notes.md +++ b/content/en/plugins/github-integration/release-notes.md @@ -5,7 +5,7 @@ weight: 99 description: > Github Integration Plugin for Spinnaker release notes. --- -## v0.3.1 2023/12/21 +## v0.3.1 2023/11/21 ### Features - Added support for GitHub Commit Statuses notifications for pipelines and/or stages using Echo service. See [Configure GitHub Commit Status Echo notifications](/plugins/github-integration/install/configure/#configure-github-commit-status-echo-notifications) for more information. - Added GitHub Commit Status stage for pipelines. See [Create GitHub Commit Status](/plugins/github-integration/use/#create-github-commit-status) for more information. From eeceb423f1c0c47a43cde21d60bc423f92cf435f Mon Sep 17 00:00:00 2001 From: Aimee Ukasick Date: Tue, 28 Nov 2023 16:13:56 -0600 Subject: [PATCH 18/21] break advanced configure into 3 separate pages --- .../en/plugins/github-integration/authz.md | 99 +++++++ .../commit-status-notifications.md | 82 ++++++ .../github-integration/install/configure.md | 263 ------------------ content/en/plugins/github-integration/use.md | 4 +- .../validate-github-access.md | 106 +++++++ 5 files changed, 289 insertions(+), 265 deletions(-) create mode 100644 content/en/plugins/github-integration/authz.md create mode 100644 content/en/plugins/github-integration/commit-status-notifications.md delete mode 100644 content/en/plugins/github-integration/install/configure.md create mode 100644 content/en/plugins/github-integration/validate-github-access.md diff --git a/content/en/plugins/github-integration/authz.md b/content/en/plugins/github-integration/authz.md new file mode 100644 index 0000000000..8fd10466b2 --- /dev/null +++ b/content/en/plugins/github-integration/authz.md @@ -0,0 +1,99 @@ +--- +title: Enable and Configure AuthZ in the GitHub Integration Plugin +linkTitle: Enable AuthZ +weight: 10 +description: > + Learn how to enable and configure AuthZ support for GitHub App accounts. +--- + + +![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) + +## Authorization (AuthZ) + +This feature enables AuthZ support for GitHub App accounts. + +Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. + +### How this feature works + +The GitHub Integration plugin supports Fiat authz for GitHub App accounts configured to determine whether a role or group can perform the following actions: + +- `READ`: A user can view the GitHub App account's configuration and/or use it as a trigger source. +- `WRITE`: A user can use the GitHub App account as the target account for the GitHub integration plugin stages. + + +```mermaid +sequenceDiagram + participant user as User + participant gate as Gate + participant orca as Orca + participant igor as Igor + participant fiat as Fiat + participant gh as GitHub + +user ->> gate: Start execution for pipeline (includes plugin stage) +gate ->> orca: Submit execution for pipeline (includes plugin stage) +orca ->> igor: Submit the task operations of plugin stage +igor ->> fiat: Check hasPermissions +alt Unauthorized + fiat ->> igor: hasPermissions=false + igor ->> orca: Fail with Forbidden + orca ->> gate: TERMINAL +else Authorized + fiat ->> igor: hasPermissions=true + igor ->> orca: IN_PROGRESS + igor ->> gh: API calls + orca ->> gate: IN_PROGRESS +end +``` + +### {{% heading "prereq" %}} + +- You are familiar with how Spinnaker's [AuthZ]({{< ref "continuous-deployment/overview/fiat-permissions-overview" >}}) works. +- You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/_index.md" >}}). +- You have enabled Fiat in your Spinnaker or Armory CD instance integrated with an external identity provider (IDP). + +### How to enable AuthZ support + +You can enable AuthZ support per GitHub App account by setting the `permissions` block in the `github-integration-plugin.yml` file. For example: + +{{< highlight yaml "linenos=table,hl_lines=10-17 32-37" >}} +github: + plugin: + accounts: + - name: FirstAppRepo + organization: company-public + repository: first-app-repo + defaultBranch: master + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: + READ: + - "read-only-role" + - "dev-role" + - "ops-role" + EXECUTE: + - "dev-role" + - "ops-role" + - name: SecondAppRepo + organization: company-public + repository: second-app-repo + defaultBranch: main + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: [] + - name: CompanyPrivateOrgAllRepos + organization: company-private + orgWideInstallation: true + includePublicRepositories: false + defaultBranch: main + githubAppId: 1357 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey + permissions: + READ: + - "read-only-role" + - "ops-role" + EXECUTE: + - "ops-role" +{{< /highlight >}} diff --git a/content/en/plugins/github-integration/commit-status-notifications.md b/content/en/plugins/github-integration/commit-status-notifications.md new file mode 100644 index 0000000000..9ebdfeb652 --- /dev/null +++ b/content/en/plugins/github-integration/commit-status-notifications.md @@ -0,0 +1,82 @@ +--- +title: Configure GitHub Commit Status Echo notifications +linkTitle: GitHub Notifications +weight: 10 +description: > + Learn how to enable an enhanced Echo notification type which can be configured to send notifications for pipelines and/or stages statuses with custom context and description linking to the Spinnaker UI as a target URL. +--- + +![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) + + +## Configure GitHub Commit Status Echo notifications + +Echo is the microservice in Spinnaker which (among other functionalities) manages notifications for Spinnaker pipelines and stages. +Using the GitHub Integration plugin you can configure Echo to create [GitHub Commit Statuses](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) +in a repository by authenticating using the GitHub App accounts configured in the plugin. + +## How this feature works + +GitHub Integration plugin offers an enhanced Echo notification type which can be configured to send notifications +for pipelines and/or stages statuses with custom context and description linking to the Spinnaker UI as a target URL. + +## How to enable + +GitHub Commit Status notifications can be enabled per GitHub App account by enabling the feature in Echo and Deck services +in the `github-integration-plugin.yml` file. + +{{< highlight yaml "linenos=table,hl_lines=7-8 14-15" >}} +spec: + spinnakerConfig: + profiles: + spinnaker: + github: + plugin: + github-status: + enabled: true + accounts: [] + deck: + settings-local.js: | + window.spinnakerSettings = { + ... (content omitted for brevity) + feature.githubIntegrationFlags = { + githubStatus: true + }; + ... (content omitted for brevity) + } +{{< /highlight >}} + +## Migrating from Echo's default implementation + +Migrating from the default implementation to the GitHub Integration plugin's implementation does not require any changes in your pipelines. +The GitHub Integration plugin's implementation will be used automatically when the feature is enabled in Echo and Deck services and the default +implementation is disabled. To ensure a smooth migration, follow these steps: + + +1. Disable the default implementation by disabling the `github-status` feature in Echo and Deck services + + {{< highlight yaml "linenos=table,hl_lines=6 13" >}} + spec: + spinnakerConfig: + profiles: + echo: + github-status: + enabled: false + token: + endpoint: https://api.github.com + deck: + settings-local.js: | + window.spinnakerSettings = { + ... (content omitted for brevity) + notifications.githubStatus.enabled = false; + ... (content omitted for brevity) + } + {{< /highlight >}} + +1. Enable the GitHub Integration plugin's implementation as described in the previous section. + +1. Ensure that you have configured the appropriate GitHub App accounts for every GitHub organisation that you want to +send notifications to as described in the [GitHub App accounts configuration](#github-app-accounts-configuration) section. + +1. Verify that the Deck UI is showing the plugin's Commit Status notification type in the notification settings for +your pipelines and the Commit Statuses are being created in GitHub. diff --git a/content/en/plugins/github-integration/install/configure.md b/content/en/plugins/github-integration/install/configure.md deleted file mode 100644 index ee642b8b3a..0000000000 --- a/content/en/plugins/github-integration/install/configure.md +++ /dev/null @@ -1,263 +0,0 @@ ---- -title: Configure GitHub Integration Features -linkTitle: Configure Features -weight: 10 -description: > - Learn how to configure advanced GitHub Integration features in your Spinnaker or Armory CD instance. ---- - -![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) - -## Authorization (AuthZ) - -This feature enables AuthZ support for GitHub App accounts. - -Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. - -### How this feature works - -The GitHub Integration plugin supports Fiat authz for GitHub App accounts configured to determine whether a role or group can perform the following actions: - -- `READ`: A user can view the GitHub App account's configuration and/or use it as a trigger source. -- `WRITE`: A user can use the GitHub App account as the target account for the GitHub integration plugin stages. - - -```mermaid -sequenceDiagram - participant user as User - participant gate as Gate - participant orca as Orca - participant igor as Igor - participant fiat as Fiat - participant gh as GitHub - -user ->> gate: Start execution for pipeline (includes plugin stage) -gate ->> orca: Submit execution for pipeline (includes plugin stage) -orca ->> igor: Submit the task operations of plugin stage -igor ->> fiat: Check hasPermissions -alt Unauthorized - fiat ->> igor: hasPermissions=false - igor ->> orca: Fail with Forbidden - orca ->> gate: TERMINAL -else Authorized - fiat ->> igor: hasPermissions=true - igor ->> orca: IN_PROGRESS - igor ->> gh: API calls - orca ->> gate: IN_PROGRESS -end -``` - -### {{% heading "prereq" %}} - -- You are familiar with how Spinnaker's [AuthZ]({{< ref "continuous-deployment/overview/fiat-permissions-overview" >}}) works. -- You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/_index.md" >}}). -- You have enabled Fiat in your Spinnaker or Armory CD instance integrated with an external identity provider (IDP). - -### How to enable AuthZ support - -You can enable AuthZ support per GitHub App account by setting the `permissions` block in the `github-integration-plugin.yml` file. For example: - -{{< highlight yaml "linenos=table,hl_lines=10-17 32-37" >}} -github: - plugin: - accounts: - - name: FirstAppRepo - organization: company-public - repository: first-app-repo - defaultBranch: master - githubAppId: 9753 - githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey - permissions: - READ: - - "read-only-role" - - "dev-role" - - "ops-role" - EXECUTE: - - "dev-role" - - "ops-role" - - name: SecondAppRepo - organization: company-public - repository: second-app-repo - defaultBranch: main - githubAppId: 9753 - githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey - permissions: [] - - name: CompanyPrivateOrgAllRepos - organization: company-private - orgWideInstallation: true - includePublicRepositories: false - defaultBranch: main - githubAppId: 1357 - githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey - permissions: - READ: - - "read-only-role" - - "ops-role" - EXECUTE: - - "ops-role" -{{< /highlight >}} - -## Validate GitHub access - -This feature validates GitHub access based on configuration assigned to a GitHub App account. - -Using the `impersonateGitHubTeam` feature, you can validate and enforce GitHub App account access to repositories based on the GitHub team's assigned configuration. - -### How this feature works - -Before performing any action in a pipeline stage, the plugin validates that the GitHub teams configured using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: - -- `Admin`: Full access to the repository -- `Write`: Read and write access to the repository -- `Maintain`: Read and write access to the repository, including managing issues and pull requests - -If the GitHub team does not have appropriate access to the repository, the pipeline stage fails with an error message. - -```mermaid -sequenceDiagram - participant user as User - participant gate as Gate - participant orca as Orca - participant igor as Igor - participant fiat as Fiat - participant gh as GitHub - -user ->> gate: Start execution for pipeline (includes plugin stage) -gate ->> orca: Submit execution for pipeline (includes plugin stage) -orca ->> igor: Submit the task operations of plugin stage -igor ->> fiat: Check hasPermissions -alt Unauthorized - fiat ->> igor: hasPermissions=false - igor ->> orca: Fail with Forbidden - orca ->> gate: TERMINAL -else Authorized - fiat ->> igor: hasPermissions=true - igor ->> gh: Check permissions on Repository - gh ->> igor: Permissions - igor ->> igor: Evaluate Repo permissions - alt Unauthorized_onRepo - igor ->> orca: Fail with Forbidden on Repo Access - else Authorized_onRepo - orca ->> gate: IN_PROGRESS - end -end -``` - -### How to enable - -You enable the `impersonateGitHubTeam` feature per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. For example: - -{{< highlight yaml "linenos=table,hl_lines=26-28 36-37" >}} -github: - plugin: - accounts: - - name: FirstAppRepo - organization: company-public - repository: first-app-repo - defaultBranch: master - githubAppId: 9753 - githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey - permissions: - READ: - - "read-only-role" - - "dev-role" - - "ops-role" - EXECUTE: - - "dev-role" - - "ops-role" - impersonateGitHubTeam: [] - - name: SecondAppRepo - organization: company-public - repository: second-app-repo - defaultBranch: main - githubAppId: 9753 - githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey - permissions: [] - impersonateGitHubTeam: - - "dev-github-team" - - "ops-github-team" - - name: CompanyPrivateOrgAllRepos - organization: company-private - orgWideInstallation: true - includePublicRepositories: false - defaultBranch: main - githubAppId: 1357 - githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey - impersonateGitHubTeam: - - "admin-github-team" - permissions: - READ: - - "read-only-role" - - "ops-role" - EXECUTE: - - "ops-role" -{{< /highlight >}} - -## Configure GitHub Commit Status Echo notifications -Echo is the microservice in Spinnaker which (among other functionalities) manages notifications for Spinnaker pipelines and stages. -Using the GitHub Integration plugin you can configure Echo to create [GitHub Commit Statuses](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) -in a repository by authenticating using the GitHub App accounts configured in the plugin. - -### How this feature works - -GitHub Integration plugin offers an enhanced Echo notification type which can be configured to send notifications -for pipelines and/or stages statuses with custom context and description linking to the Spinnaker UI as a target URL. - -### How to enable - -GitHub Commit Status notifications can be enabled per GitHub App account by enabling the feature in Echo and Deck services -in the `github-integration-plugin.yml` file. - -{{< highlight yaml "linenos=table,hl_lines=7-8 14-15" >}} -spec: - spinnakerConfig: - profiles: - spinnaker: - github: - plugin: - github-status: - enabled: true - accounts: [] - deck: - settings-local.js: | - window.spinnakerSettings = { - ... (content omitted for brevity) - feature.githubIntegrationFlags = { - githubStatus: true - }; - ... (content omitted for brevity) - } -{{< /highlight >}} - -### Migrating from Echo's default implementation - -Migrating from the default implementation to the GitHub Integration plugin's implementation does not require any changes in your pipelines. -The GitHub Integration plugin's implementation will be used automatically when the feature is enabled in Echo and Deck services and the default -implementation is disabled. To ensure a smooth migration, follow these steps: - - -1. Disable the default implementation by disabling the `github-status` feature in Echo and Deck services: -{{< highlight yaml "linenos=table,hl_lines=6 13" >}} -spec: - spinnakerConfig: - profiles: - echo: - github-status: - enabled: false - token: - endpoint: https://api.github.com - deck: - settings-local.js: | - window.spinnakerSettings = { - ... (content omitted for brevity) - notifications.githubStatus.enabled = false; - ... (content omitted for brevity) - } -{{< /highlight >}} -2. Enable the GitHub Integration plugin's implementation as described in the previous section. - -3. Ensure that you have configured the appropriate GitHub App accounts for every GitHub organisation that you want to -send notifications to as described in the [GitHub App accounts configuration](#github-app-accounts-configuration) section. - -4. Verify that the Deck UI is showing the plugin's Commit Status notification type in the notification settings for -your pipelines and the Commit Statuses are being created in GitHub. diff --git a/content/en/plugins/github-integration/use.md b/content/en/plugins/github-integration/use.md index 9b8f9f5f0d..51bb8623eb 100644 --- a/content/en/plugins/github-integration/use.md +++ b/content/en/plugins/github-integration/use.md @@ -1,7 +1,7 @@ --- title: Use the GitHub Integration Plugin -linkTitle: How to Use -weight: 5 +linkTitle: Use GitHub Integration +weight: 20 description: > Learn how to use the GitHub Integration plugin to trigger Spinnaker pipelines from GitHub and also to trigger GitHub workflows from Spinnaker pipelines. --- diff --git a/content/en/plugins/github-integration/validate-github-access.md b/content/en/plugins/github-integration/validate-github-access.md new file mode 100644 index 0000000000..20eed2310e --- /dev/null +++ b/content/en/plugins/github-integration/validate-github-access.md @@ -0,0 +1,106 @@ +--- +title: Validate GitHub Access +linkTitle: Validate GitHub Access +weight: 10 +description: > + Learn how to enable the GitHub Integration feature that validates GitHub access based on configuration assigned to a GitHub App account. +--- + +![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) + + +## Validate GitHub access + +This feature validates GitHub access based on configuration assigned to a GitHub App account. + +Using the `impersonateGitHubTeam` feature, you can validate and enforce GitHub App account access to repositories based on the GitHub team's assigned configuration. + +### How this feature works + +Before performing any action in a pipeline stage, the plugin validates that the GitHub teams configured using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: + +- `Admin`: Full access to the repository +- `Write`: Read and write access to the repository +- `Maintain`: Read and write access to the repository, including managing issues and pull requests + +If the GitHub team does not have appropriate access to the repository, the pipeline stage fails with an error message. + +```mermaid +sequenceDiagram + participant user as User + participant gate as Gate + participant orca as Orca + participant igor as Igor + participant fiat as Fiat + participant gh as GitHub + +user ->> gate: Start execution for pipeline (includes plugin stage) +gate ->> orca: Submit execution for pipeline (includes plugin stage) +orca ->> igor: Submit the task operations of plugin stage +igor ->> fiat: Check hasPermissions +alt Unauthorized + fiat ->> igor: hasPermissions=false + igor ->> orca: Fail with Forbidden + orca ->> gate: TERMINAL +else Authorized + fiat ->> igor: hasPermissions=true + igor ->> gh: Check permissions on Repository + gh ->> igor: Permissions + igor ->> igor: Evaluate Repo permissions + alt Unauthorized_onRepo + igor ->> orca: Fail with Forbidden on Repo Access + else Authorized_onRepo + orca ->> gate: IN_PROGRESS + end +end +``` + +### How to enable + +You enable the `impersonateGitHubTeam` feature per GitHub App account by setting the `impersonateGitHubTeam` block in the `github-integration-plugin.yml` file. For example: + +{{< highlight yaml "linenos=table,hl_lines=26-28 36-37" >}} +github: + plugin: + accounts: + - name: FirstAppRepo + organization: company-public + repository: first-app-repo + defaultBranch: master + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: + READ: + - "read-only-role" + - "dev-role" + - "ops-role" + EXECUTE: + - "dev-role" + - "ops-role" + impersonateGitHubTeam: [] + - name: SecondAppRepo + organization: company-public + repository: second-app-repo + defaultBranch: main + githubAppId: 9753 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-9753-privatekey + permissions: [] + impersonateGitHubTeam: + - "dev-github-team" + - "ops-github-team" + - name: CompanyPrivateOrgAllRepos + organization: company-private + orgWideInstallation: true + includePublicRepositories: false + defaultBranch: main + githubAppId: 1357 + githubAppPrivateKey: encrypted:k8s!n:spin-secrets!k:github-app-1357-privatekey + impersonateGitHubTeam: + - "admin-github-team" + permissions: + READ: + - "read-only-role" + - "ops-role" + EXECUTE: + - "ops-role" +{{< /highlight >}} \ No newline at end of file From ecc8ad498935587a15bf7f497ea45d70c4891c54 Mon Sep 17 00:00:00 2001 From: Aimee Ukasick Date: Fri, 1 Dec 2023 11:46:02 -0600 Subject: [PATCH 19/21] move _index to overview; move images out of static/images add new features with links to overview --- .../includes/plugins/github/install-reqs.md | 2 +- .../en/plugins/github-integration/_index.md | 83 --------------- .../en/plugins/github-integration/authz.md | 2 +- .../commit-status-notifications.md | 18 ++-- .../github-integration/install/_index.md | 36 ++++++- .../github-integration/install/armory-cd.md | 2 +- .../en/plugins/github-integration/overview.md | 95 ++++++++++++++++++ .../github-integration/use}/commitStatus.png | Bin .../use}/deploymentCreated.png | Bin .../use}/deploymentCreated2.png | Bin .../github-integration/use}/getDetails.png | Bin .../{use.md => use/index.md} | 20 ++-- .../github-integration/use}/preRelease.png | Bin .../github-integration/use}/repoDispatch.png | Bin .../use}/workflowDispatch.png | Bin .../use}/workflowFinish.png | Bin .../validate-github-access.md | 3 +- 17 files changed, 150 insertions(+), 111 deletions(-) create mode 100644 content/en/plugins/github-integration/overview.md rename {static/images/plugins/github => content/en/plugins/github-integration/use}/commitStatus.png (100%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/deploymentCreated.png (100%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/deploymentCreated2.png (100%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/getDetails.png (100%) rename content/en/plugins/github-integration/{use.md => use/index.md} (88%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/preRelease.png (100%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/repoDispatch.png (100%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/workflowDispatch.png (100%) rename {static/images/plugins/github => content/en/plugins/github-integration/use}/workflowFinish.png (100%) diff --git a/content/en/includes/plugins/github/install-reqs.md b/content/en/includes/plugins/github/install-reqs.md index db05b5c9ba..1ce543bc79 100644 --- a/content/en/includes/plugins/github/install-reqs.md +++ b/content/en/includes/plugins/github/install-reqs.md @@ -1,2 +1,2 @@ -* You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/_index.md" >}}). +* You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/overview.md" >}}). * You are familiar with [GitHub Apps](https://docs.github.com/en/apps/overview). diff --git a/content/en/plugins/github-integration/_index.md b/content/en/plugins/github-integration/_index.md index fa447c58c1..8e16c008cc 100644 --- a/content/en/plugins/github-integration/_index.md +++ b/content/en/plugins/github-integration/_index.md @@ -1,91 +1,8 @@ --- title: GitHub Integration Plugin for Spinnaker linkTitle: GitHub Integration -no_list: true description: > Armory's GitHub Integration plugin for Spinnaker streamlines integration with GitHub Actions, filling the native support gap. The plugin enables easy triggering of GitHub Actions workflows, dynamic control of Spinnaker pipelines based on workflow outcomes, and seamless synchronization of GitHub Deployment statuses with Spinnaker pipeline conclusions. --- ![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) - -## GitHub Integration Plugin features - -The GitHub Integration Plugin provides the following GitHub integration features: - -- Trigger a GitHub Actions workflow from a Spinnaker pipeline using **workflow_dispatch** or **repository_dispatch** events -- Trigger a Spinnaker pipeline automatically when a GitHub workflow finishes successfully -- Trigger a Spinnaker pipeline when GitHub creates a new GitHub Deployment -- Monitor a GitHub workflow and finish pipeline execution based on the GitHub workflow result -- Update GitHub deployment status based on Spinnaker pipeline outcome -- View GitHub Action Logs in Spinnaker -- there is no need to navigate to GitHub to view the logs - -The GitHub Integration plugin uses [GitHub Apps](https://docs.github.com/en/apps/overview) to integrate with GitHub. GitHup Apps provide webhooks and narrow, specific permissions. You can install a GitHub App that gives the GitHub Integration plugin access to all the repos in your GitHub organization, or you can install a Github App that gives the GitHub Integration plugin access to specific repos. You can install as many GitHub Apps as your use case requires. - -## How the plugin works with GitHub - -```mermaid -graph TD - Orca -->|Workflow Trigger| Igor - Gate --> |Trigger based on Deployment event|Echo - Igor -->|Trigger/Monitor triggered workflows| GitHub - Echo -->|Pipeline triggers|Orca - Orca -->|Pipeline notifications|Echo - GitHub --> |Deployment event| Gate - Echo --> |Notifications|GitHub -``` - -For example, the plugin processes a GitHub Deployment event like this: - -```mermaid -sequenceDiagram -participant ghActions as "GitHub Workflow job" -participant gh as "GitHub" -participant gate as "Gate" -participant echo as "Echo" -participant orca as "Orca" - -ghActions ->> gh: "Create Deployment" -gh ->> ghActions: "Deployment created" -gh ->> gate: "Deployment Event" -gate ->> echo: "Deployment trigger event" -echo ->> orca: "Trigger pipelines matching the Trigger event" -orca ->> gh: "Deployment status update: in_progress, success, failure, or error" -``` - -## Compatibility matrix - -{{< include "plugins/github/compat-matrix.md" >}} - -## Installation paths - -{{% cardpane %}} -{{% card header="Armory CD
Armory Operator" %}} -Use a Kustomize patch to install the plugin. - -1. Create a GitHub App and install it in your repo or organization. -1. Configure the plugin with your GitHub repo(s) and/or organization(s). -1. Install the plugin using the Armory Operator. - -[Instructions]({{< ref "plugins/github-integration/install/armory-cd" >}}) -{{% /card %}} - -{{% card header="Spinnaker
Spinnaker Operator" %}} -Use a Kustomize patch to install the plugin. - -1. Create a GitHub App and install it in your repo. -1. Configure the plugin with your GitHub repo(s) and/or organization(s). -1. Install the plugin using the Spinnaker Operator. - -[Instructions]({{< ref "plugins/github-integration/install/spinnaker-operator" >}}) -{{% /card %}} - -{{% card header="Spinnaker
Halyard" %}} -Use Spinnaker local config files to install the plugin. - -1. Create a GitHub App and install it in your repo. -1. Configure the plugin with your GitHub repo(s) and/or organization(s). -1. Install the plugin in local config files and apply those changes using Halyard. - -[Instructions]({{< ref "plugins/github-integration/install/spinnaker-halyard" >}}) -{{% /card %}} -{{% /cardpane %}} diff --git a/content/en/plugins/github-integration/authz.md b/content/en/plugins/github-integration/authz.md index 8fd10466b2..0f08675dbd 100644 --- a/content/en/plugins/github-integration/authz.md +++ b/content/en/plugins/github-integration/authz.md @@ -51,7 +51,7 @@ end ### {{% heading "prereq" %}} - You are familiar with how Spinnaker's [AuthZ]({{< ref "continuous-deployment/overview/fiat-permissions-overview" >}}) works. -- You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/_index.md" >}}). +- You have read the GitHub Integration Plugin [overview]({{< ref "plugins/github-integration/overview.md" >}}). - You have enabled Fiat in your Spinnaker or Armory CD instance integrated with an external identity provider (IDP). ### How to enable AuthZ support diff --git a/content/en/plugins/github-integration/commit-status-notifications.md b/content/en/plugins/github-integration/commit-status-notifications.md index 9ebdfeb652..4af608d0e9 100644 --- a/content/en/plugins/github-integration/commit-status-notifications.md +++ b/content/en/plugins/github-integration/commit-status-notifications.md @@ -1,6 +1,6 @@ --- -title: Configure GitHub Commit Status Echo notifications -linkTitle: GitHub Notifications +title: Enable GitHub Commit Status Echo notifications +linkTitle: Enable Notifications weight: 10 description: > Learn how to enable an enhanced Echo notification type which can be configured to send notifications for pipelines and/or stages statuses with custom context and description linking to the Spinnaker UI as a target URL. @@ -12,6 +12,7 @@ description: > ## Configure GitHub Commit Status Echo notifications Echo is the microservice in Spinnaker which (among other functionalities) manages notifications for Spinnaker pipelines and stages. + Using the GitHub Integration plugin you can configure Echo to create [GitHub Commit Statuses](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) in a repository by authenticating using the GitHub App accounts configured in the plugin. @@ -22,8 +23,7 @@ for pipelines and/or stages statuses with custom context and description linking ## How to enable -GitHub Commit Status notifications can be enabled per GitHub App account by enabling the feature in Echo and Deck services -in the `github-integration-plugin.yml` file. +GitHub Commit Status notifications can be enabled per GitHub App account by enabling the feature in Echo and Deck services in the `github-integration-plugin.yml` file. {{< highlight yaml "linenos=table,hl_lines=7-8 14-15" >}} spec: @@ -48,9 +48,7 @@ spec: ## Migrating from Echo's default implementation -Migrating from the default implementation to the GitHub Integration plugin's implementation does not require any changes in your pipelines. -The GitHub Integration plugin's implementation will be used automatically when the feature is enabled in Echo and Deck services and the default -implementation is disabled. To ensure a smooth migration, follow these steps: +Migrating from the default implementation to the GitHub Integration plugin's implementation does not require any changes in your pipelines. The GitHub Integration plugin's implementation is used automatically when the feature is enabled in Echo and Deck services and the default implementation is disabled. To ensure a smooth migration, follow these steps: 1. Disable the default implementation by disabling the `github-status` feature in Echo and Deck services @@ -73,10 +71,10 @@ implementation is disabled. To ensure a smooth migration, follow these steps: } {{< /highlight >}} -1. Enable the GitHub Integration plugin's implementation as described in the previous section. +1. Enable the GitHub Integration plugin. See the [Get Started]({{< ref "plugins/github-integration/install/_index.md" >}}) section for instructions. -1. Ensure that you have configured the appropriate GitHub App accounts for every GitHub organisation that you want to -send notifications to as described in the [GitHub App accounts configuration](#github-app-accounts-configuration) section. +1. Ensure that you have configured the appropriate GitHub App accounts for every GitHub organization that you want to send notifications to. 1. Verify that the Deck UI is showing the plugin's Commit Status notification type in the notification settings for your pipelines and the Commit Statuses are being created in GitHub. + diff --git a/content/en/plugins/github-integration/install/_index.md b/content/en/plugins/github-integration/install/_index.md index 16ca8a26ad..47a4abb2ef 100644 --- a/content/en/plugins/github-integration/install/_index.md +++ b/content/en/plugins/github-integration/install/_index.md @@ -1,7 +1,39 @@ --- title: Get Started with the GitHub Integration Plugin linkTitle: Get Started -weight: 1 +weight: 2 description: > - In this section, learn how to install the GitHub Integration Plugin for Spinnaker and Armory Continuous Deployment. + In this section, learn how to install the GitHub Integration Plugin for Spinnaker and Armory Continuous Deployment. Use the Armory Operator with Armory CD. Spinnaker users can install the plugin using the Spinnaker Operator or Halyard. --- + +{{% cardpane %}} +{{% card header="Armory CD
Armory Operator" %}} +Use a Kustomize patch to install the plugin. + +1. Create a GitHub App and install it in your repo or organization. +1. Configure the plugin with your GitHub repo(s) and/or organization(s). +1. Install the plugin using the Armory Operator. + +[Instructions]({{< ref "plugins/github-integration/install/armory-cd" >}}) +{{% /card %}} + +{{% card header="Spinnaker
Spinnaker Operator" %}} +Use a Kustomize patch to install the plugin. + +1. Create a GitHub App and install it in your repo. +1. Configure the plugin with your GitHub repo(s) and/or organization(s). +1. Install the plugin using the Spinnaker Operator. + +[Instructions]({{< ref "plugins/github-integration/install/spinnaker-operator" >}}) +{{% /card %}} + +{{% card header="Spinnaker
Halyard" %}} +Use Spinnaker local config files to install the plugin. + +1. Create a GitHub App and install it in your repo. +1. Configure the plugin with your GitHub repo(s) and/or organization(s). +1. Install the plugin in local config files and apply those changes using Halyard. + +[Instructions]({{< ref "plugins/github-integration/install/spinnaker-halyard" >}}) +{{% /card %}} +{{% /cardpane %}} \ No newline at end of file diff --git a/content/en/plugins/github-integration/install/armory-cd.md b/content/en/plugins/github-integration/install/armory-cd.md index 102a6a4dcb..a37112289f 100644 --- a/content/en/plugins/github-integration/install/armory-cd.md +++ b/content/en/plugins/github-integration/install/armory-cd.md @@ -40,7 +40,7 @@ Create a `github-integration-plugin.yml` file with the following contents: {{% alert title="Conflict with Armory CDSH v2.30.x" color="warning" %}} -[Known issue]({{< ref "plugins/github-integration/release-notes#armoryheader-plugin-conflict" >}}): The GitHub Integration plugin conflicts with the Armory.Header plugin version included in CDSH v2.30.x. You must install version 0.2.0 of the Armory.Header plugin. +[Known issue]({{< ref "plugins/github-integration/release-notes#armoryheader-plugin-conflict" >}}): The GitHub Integration plugin conflicts with the Armory.Header plugin version included in Armory CD v2.30.x. You must install version 0.2.0 of the Armory.Header plugin.
Show me how {{< include "plugins/github/armory-header-plugin.md" >}}
diff --git a/content/en/plugins/github-integration/overview.md b/content/en/plugins/github-integration/overview.md new file mode 100644 index 0000000000..556dcf5978 --- /dev/null +++ b/content/en/plugins/github-integration/overview.md @@ -0,0 +1,95 @@ +--- +title: GitHub Integration Plugin for Spinnaker Overview +linkTitle: Overview +weight: 1 +description: > + Learn about GitHub Integration Plugin features, how the plugin works, different installation paths, and the plugin's compatibility with Armory Continuous Deployment and Spinnaker versions. +--- + +![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) + + +## GitHub Integration Plugin features + +The GitHub Integration Plugin provides the following GitHub integration features: + +- [Trigger a GitHub Actions workflow]({{< ref "plugins/github-integration/use#trigger-github-workflows-from-spinnaker-pipelines" >}}) from a Spinnaker pipeline using **workflow_dispatch** or **repository_dispatch** events. +- [Trigger a Spinnaker pipeline automatically when a GitHub workflow finishes successfully]({{< ref "plugins/github-integration/use#workflow-success-trigger" >}}). +- [Trigger a Spinnaker pipeline when GitHub creates a new GitHub Deployment]({{< ref "plugins/github-integration/use#new-deployment-trigger" >}}). +- Monitor a GitHub workflow and finish pipeline execution based on the GitHub workflow result. +- [Update GitHub deployment status based on Spinnaker pipeline outcome]({{< ref "plugins/github-integration/use#create-github-commit-status" >}}). +- View GitHub Action Logs in Spinnaker -- there is no need to navigate to GitHub to view the logs. +- [Validate GitHub access]({{< ref "plugins/github-integration/validate-github-access" >}}) based on configuration assigned to a GitHub App account. +- [Create GitHub commit statuses]({{< ref "plugins/github-integration/commit-status-notifications" >}}) using Echo. +- [Use AuthZ]({{< ref "plugins/github-integration/authz" >}}) for your GitHub Accounts. + +The GitHub Integration plugin uses [GitHub Apps](https://docs.github.com/en/apps/overview) to integrate with GitHub. GitHup Apps provide webhooks and narrow, specific permissions. You can install a GitHub App that gives the GitHub Integration plugin access to all the repos in your GitHub organization, or you can install a Github App that gives the GitHub Integration plugin access to specific repos. You can install as many GitHub Apps as your use case requires. + +## How the plugin works with GitHub + +```mermaid +graph TD + Orca -->|Workflow Trigger| Igor + Gate --> |Trigger based on Deployment event|Echo + Igor -->|Trigger/Monitor triggered workflows| GitHub + Echo -->|Pipeline triggers|Orca + Orca -->|Pipeline notifications|Echo + GitHub --> |Deployment event| Gate + Echo --> |Notifications|GitHub +``` + +For example, the plugin processes a GitHub Deployment event like this: + +```mermaid +sequenceDiagram +participant ghActions as "GitHub Workflow job" +participant gh as "GitHub" +participant gate as "Gate" +participant echo as "Echo" +participant orca as "Orca" + +ghActions ->> gh: "Create Deployment" +gh ->> ghActions: "Deployment created" +gh ->> gate: "Deployment Event" +gate ->> echo: "Deployment trigger event" +echo ->> orca: "Trigger pipelines matching the Trigger event" +orca ->> gh: "Deployment status update: in_progress, success, failure, or error" +``` + +## Compatibility matrix + +{{< include "plugins/github/compat-matrix.md" >}} + +## Installation paths + +{{% cardpane %}} +{{% card header="Armory CD
Armory Operator" %}} +Use a Kustomize patch to install the plugin. + +1. Create a GitHub App and install it in your repo or organization. +1. Configure the plugin with your GitHub repo(s) and/or organization(s). +1. Install the plugin using the Armory Operator. + +[Instructions]({{< ref "plugins/github-integration/install/armory-cd" >}}) +{{% /card %}} + +{{% card header="Spinnaker
Spinnaker Operator" %}} +Use a Kustomize patch to install the plugin. + +1. Create a GitHub App and install it in your repo. +1. Configure the plugin with your GitHub repo(s) and/or organization(s). +1. Install the plugin using the Spinnaker Operator. + +[Instructions]({{< ref "plugins/github-integration/install/spinnaker-operator" >}}) +{{% /card %}} + +{{% card header="Spinnaker
Halyard" %}} +Use Spinnaker local config files to install the plugin. + +1. Create a GitHub App and install it in your repo. +1. Configure the plugin with your GitHub repo(s) and/or organization(s). +1. Install the plugin in local config files and apply those changes using Halyard. + +[Instructions]({{< ref "plugins/github-integration/install/spinnaker-halyard" >}}) +{{% /card %}} +{{% /cardpane %}} diff --git a/static/images/plugins/github/commitStatus.png b/content/en/plugins/github-integration/use/commitStatus.png similarity index 100% rename from static/images/plugins/github/commitStatus.png rename to content/en/plugins/github-integration/use/commitStatus.png diff --git a/static/images/plugins/github/deploymentCreated.png b/content/en/plugins/github-integration/use/deploymentCreated.png similarity index 100% rename from static/images/plugins/github/deploymentCreated.png rename to content/en/plugins/github-integration/use/deploymentCreated.png diff --git a/static/images/plugins/github/deploymentCreated2.png b/content/en/plugins/github-integration/use/deploymentCreated2.png similarity index 100% rename from static/images/plugins/github/deploymentCreated2.png rename to content/en/plugins/github-integration/use/deploymentCreated2.png diff --git a/static/images/plugins/github/getDetails.png b/content/en/plugins/github-integration/use/getDetails.png similarity index 100% rename from static/images/plugins/github/getDetails.png rename to content/en/plugins/github-integration/use/getDetails.png diff --git a/content/en/plugins/github-integration/use.md b/content/en/plugins/github-integration/use/index.md similarity index 88% rename from content/en/plugins/github-integration/use.md rename to content/en/plugins/github-integration/use/index.md index 51bb8623eb..b99a6c1e69 100644 --- a/content/en/plugins/github-integration/use.md +++ b/content/en/plugins/github-integration/use/index.md @@ -18,7 +18,7 @@ Use the **Github Integration Workflow Trigger Stage** to trigger your GitHub wor Configure the **Github Integration Workflow Trigger Stage** as in the following screenshot: -{{< figure src="/images/plugins/github/workflowDispatch.png" >}} +{{< figure src="workflowDispatch.png" width="80%" height="80%" >}} * **Github Account**: (Required) Select the GitHub Account; this is one of the accounts you configured when you installed the plugin * **Organization or User**: (Required) The organization or username that should trigger the workflow @@ -31,7 +31,7 @@ Configure the **Github Integration Workflow Trigger Stage** as in the following Configure the **Github Integration Workflow Trigger Stage** as in the following screenshot: -{{< figure src="/images/plugins/github/repoDispatch.png" >}} +{{< figure src="repoDispatch.png" width="80%" height="80%" >}} * **Github Account**: (Required) Select the GitHub Account; this is one of the accounts you configured when you installed the plugin * **Organization or User**: (Required) The organization or username that should trigger the workflow @@ -45,7 +45,7 @@ Configure the **Github Integration Workflow Trigger Stage** as in the following To trigger a Spinnaker pipeline when a GitHub workflow finishes successfully, configure an automated trigger in your pipeline. -{{< figure src="/images/plugins/github/workflowFinish.png" >}} +{{< figure src="workflowFinish.png" width="80%" height="80%" >}} * **Type**: (Required) Select **GitHub Workflow Trigger** * **Github Account**: (Required) Select the GitHub Account; this is one of the accounts you configured when you installed the plugin @@ -58,11 +58,11 @@ To trigger a Spinnaker pipeline when a GitHub workflow finishes successfully, co To trigger a Spinnaker pipeline when GitHub creates a new deployment, first [create a deployment event webhook in GitHub](https://docs.github.com/en/webhooks/using-webhooks/creating-webhooks). Armory strongly recommends you create a secret for the webhook. -{{< figure src="/images/plugins/github/deploymentCreated.png" >}} +{{< figure src="deploymentCreated.png" width="80%" height="80%">}} Next, configure an automated trigger to process the deployment event from GitHub. -{{< figure src="/images/plugins/github/deploymentCreated2.png" >}} +{{< figure src="deploymentCreated2.png" width="80%" height="80%" >}} * **Type**: (Required) Select **GitHub Event Trigger** * **GitHub Account**: (Required) Select the GitHub Account; this is one of the accounts you configured when you installed the plugin @@ -77,7 +77,7 @@ When the pipeline triggered by a deployment event finishes, Spinnaker automatica You can use the **GitHub Integration Releases Get Details** stage to fetch the latest release information. -{{< figure src="/images/plugins/github/getDetails.png" >}} +{{< figure src="getDetails.png" width="80%" height="80%" >}} * **Github Account**: (Required) Select the GitHub Account; this is one of the accounts you configured when you installed the plugin * **Retrieve**: (Required) Select **Get Latest Release** @@ -88,7 +88,7 @@ You can use the **GitHub Integration Releases Get Details** stage to fetch the l You can use the **GitHub Integration Releases Get Details** stage to fetch the latest prerelease information. -{{< figure src="/images/plugins/github/preRelease.png" >}} +{{< figure src="reRelease.png" width="80%" height="80%" >}} * **Github Account**: (Required) Select the GitHub Account; this is one of the accounts you configured when you installed the plugin @@ -98,13 +98,11 @@ You can use the **GitHub Integration Releases Get Details** stage to fetch the l ## Create GitHub Commit Status -The GitHub Commit Status pipeline stage allows you to create a GitHub Commit Status in a repository using the GitHub App -accounts configured in the plugin without the need to configure a notification block in your pipelines and viewing the execution -status of the stage in your pipeline's execution details. +The GitHub Commit Status pipeline stage allows you to create a GitHub Commit Status in a repository using the GitHub App accounts configured in the plugin without the need to configure a notification block in your pipelines and viewing the execution status of the stage in your pipeline's execution details. Configure the **GitHub Integration Commit Status Stage** as in the following screenshot: -{{< figure src="/images/plugins/github/commitStatus.png" >}} +{{< figure src="commitStatus.png" width="80%" height="80%" >}} * **GitHub Repo**: (Required) The full repository name including the GitHub Org. For example myorg/mygithubrepo. * **Commit Ref**: (Required) The commit reference. Can be a commit SHA, branch name (heads/BRANCH_NAME), or tag name (tags/TAG_NAME). diff --git a/static/images/plugins/github/preRelease.png b/content/en/plugins/github-integration/use/preRelease.png similarity index 100% rename from static/images/plugins/github/preRelease.png rename to content/en/plugins/github-integration/use/preRelease.png diff --git a/static/images/plugins/github/repoDispatch.png b/content/en/plugins/github-integration/use/repoDispatch.png similarity index 100% rename from static/images/plugins/github/repoDispatch.png rename to content/en/plugins/github-integration/use/repoDispatch.png diff --git a/static/images/plugins/github/workflowDispatch.png b/content/en/plugins/github-integration/use/workflowDispatch.png similarity index 100% rename from static/images/plugins/github/workflowDispatch.png rename to content/en/plugins/github-integration/use/workflowDispatch.png diff --git a/static/images/plugins/github/workflowFinish.png b/content/en/plugins/github-integration/use/workflowFinish.png similarity index 100% rename from static/images/plugins/github/workflowFinish.png rename to content/en/plugins/github-integration/use/workflowFinish.png diff --git a/content/en/plugins/github-integration/validate-github-access.md b/content/en/plugins/github-integration/validate-github-access.md index 20eed2310e..2a320bc2ba 100644 --- a/content/en/plugins/github-integration/validate-github-access.md +++ b/content/en/plugins/github-integration/validate-github-access.md @@ -1,6 +1,5 @@ --- -title: Validate GitHub Access -linkTitle: Validate GitHub Access +title: Enable GitHub Access Validation weight: 10 description: > Learn how to enable the GitHub Integration feature that validates GitHub access based on configuration assigned to a GitHub App account. From e4ebb82881d3eecde6374b33240cd9beb822330b Mon Sep 17 00:00:00 2001 From: christosarvanitis Date: Mon, 11 Dec 2023 12:10:46 +0200 Subject: [PATCH 20/21] Adding summary of the benefits for the additional features --- .../en/plugins/github-integration/authz.md | 19 +++++++++++++++++-- .../commit-status-notifications.md | 3 +++ .../validate-github-access.md | 4 +++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/content/en/plugins/github-integration/authz.md b/content/en/plugins/github-integration/authz.md index 0f08675dbd..f0986a509f 100644 --- a/content/en/plugins/github-integration/authz.md +++ b/content/en/plugins/github-integration/authz.md @@ -11,9 +11,24 @@ description: > ## Authorization (AuthZ) -This feature enables AuthZ support for GitHub App accounts. +This feature enables AuthZ support for GitHub App accounts providing: + +**Compliance and Security** +* Authz for GitHub App accounts allows you to enforce access controls on a per-account basis, securing access to specific +repositories and/or GitHub organisations to only authorised groups/teams. + +**Granular Control** +* Authz for GitHub App accounts provides granular control over who can perform actions within each account. This +fine-grained permission control is crucial for maintaining a least privilege principle, where users have only the necessary access to perform their tasks, reducing the overall security surface. + +**Scalability** +* Authz for GitHub App accounts scales effectively as the number of accounts grows. This scalability is essential for +organizations managing diverse and expanding infrastructure, ensuring that access controls remain manageable +and effective. + +Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. +It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. -Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. ### How this feature works diff --git a/content/en/plugins/github-integration/commit-status-notifications.md b/content/en/plugins/github-integration/commit-status-notifications.md index 4af608d0e9..aa3eb1fba9 100644 --- a/content/en/plugins/github-integration/commit-status-notifications.md +++ b/content/en/plugins/github-integration/commit-status-notifications.md @@ -16,6 +16,9 @@ Echo is the microservice in Spinnaker which (among other functionalities) manage Using the GitHub Integration plugin you can configure Echo to create [GitHub Commit Statuses](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) in a repository by authenticating using the GitHub App accounts configured in the plugin. +By using the GitHub Integration's plugin GitHub Commit Status notifications you can link the deployment pipeline statuses +to GitHub status checks providing clear and immediate feedback to Developers about the deployment pipeline status. + ## How this feature works GitHub Integration plugin offers an enhanced Echo notification type which can be configured to send notifications diff --git a/content/en/plugins/github-integration/validate-github-access.md b/content/en/plugins/github-integration/validate-github-access.md index 2a320bc2ba..3d64cc5f93 100644 --- a/content/en/plugins/github-integration/validate-github-access.md +++ b/content/en/plugins/github-integration/validate-github-access.md @@ -10,10 +10,12 @@ description: > ## Validate GitHub access -This feature validates GitHub access based on configuration assigned to a GitHub App account. +This feature validates GitHub access based on configuration assigned to a GitHub App account providing an additional +**access control** validation layer of a GitHub App account in Spinnaker against the defined GitHub Teams in the repository. Using the `impersonateGitHubTeam` feature, you can validate and enforce GitHub App account access to repositories based on the GitHub team's assigned configuration. + ### How this feature works Before performing any action in a pipeline stage, the plugin validates that the GitHub teams configured using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: From c544b305dd45550685558af4d40584d0e144c646 Mon Sep 17 00:00:00 2001 From: Aimee Ukasick Date: Tue, 12 Dec 2023 09:25:12 -0600 Subject: [PATCH 21/21] minor copy edits --- .../en/plugins/github-integration/authz.md | 23 +++++++++---------- .../commit-status-notifications.md | 3 +-- .../validate-github-access.md | 4 +--- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/content/en/plugins/github-integration/authz.md b/content/en/plugins/github-integration/authz.md index f0986a509f..3bcc461795 100644 --- a/content/en/plugins/github-integration/authz.md +++ b/content/en/plugins/github-integration/authz.md @@ -9,22 +9,21 @@ description: > ![Proprietary](/images/proprietary.svg) ![Beta](/images/beta.svg) -## Authorization (AuthZ) +## AuthZ plugin overview -This feature enables AuthZ support for GitHub App accounts providing: +This feature enables AuthZ support for GitHub App accounts and provides these features: -**Compliance and Security** -* Authz for GitHub App accounts allows you to enforce access controls on a per-account basis, securing access to specific -repositories and/or GitHub organisations to only authorised groups/teams. +* **Compliance and Security** -**Granular Control** -* Authz for GitHub App accounts provides granular control over who can perform actions within each account. This -fine-grained permission control is crucial for maintaining a least privilege principle, where users have only the necessary access to perform their tasks, reducing the overall security surface. + Authz for GitHub App accounts allows you to enforce access controls on a per-account basis, securing access to specific repositories and/or GitHub organizations to only authorized groups/teams. -**Scalability** -* Authz for GitHub App accounts scales effectively as the number of accounts grows. This scalability is essential for -organizations managing diverse and expanding infrastructure, ensuring that access controls remain manageable -and effective. +* **Granular Control** + + Authz for GitHub App accounts provides granular control over who can perform actions within each account. This fine-grained permission control is crucial for maintaining a least privilege principle, where users have only the necessary access to perform their tasks, reducing the overall security surface. + +* **Scalability** + + Authz for GitHub App accounts scales effectively as the number of accounts grows. This scalability is essential for organizations managing diverse and expanding infrastructure, ensuring that access controls remain manageable and effective. Fiat is the Spinnaker microservice responsible for authorization (authz) for the other Spinnaker services. It is not enabled by default, so users are able to perform any action in Spinnaker. When enabled, Fiat checks the user's permissions before allowing the action to proceed. diff --git a/content/en/plugins/github-integration/commit-status-notifications.md b/content/en/plugins/github-integration/commit-status-notifications.md index aa3eb1fba9..ab2f5c5777 100644 --- a/content/en/plugins/github-integration/commit-status-notifications.md +++ b/content/en/plugins/github-integration/commit-status-notifications.md @@ -16,8 +16,7 @@ Echo is the microservice in Spinnaker which (among other functionalities) manage Using the GitHub Integration plugin you can configure Echo to create [GitHub Commit Statuses](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) in a repository by authenticating using the GitHub App accounts configured in the plugin. -By using the GitHub Integration's plugin GitHub Commit Status notifications you can link the deployment pipeline statuses -to GitHub status checks providing clear and immediate feedback to Developers about the deployment pipeline status. +By using the GitHub Integration's plugin GitHub Commit Status notifications, you can link the deployment pipeline statuses to GitHub status checks. This feature provides clear and immediate feedback to developers about the deployment pipeline status. ## How this feature works diff --git a/content/en/plugins/github-integration/validate-github-access.md b/content/en/plugins/github-integration/validate-github-access.md index 3d64cc5f93..d72a49ad9a 100644 --- a/content/en/plugins/github-integration/validate-github-access.md +++ b/content/en/plugins/github-integration/validate-github-access.md @@ -10,12 +10,10 @@ description: > ## Validate GitHub access -This feature validates GitHub access based on configuration assigned to a GitHub App account providing an additional -**access control** validation layer of a GitHub App account in Spinnaker against the defined GitHub Teams in the repository. +This feature validates GitHub access based on configuration assigned to a GitHub App account, providing an additional **access control** validation layer of a GitHub App account in Spinnaker against the defined GitHub Teams in the repository. Using the `impersonateGitHubTeam` feature, you can validate and enforce GitHub App account access to repositories based on the GitHub team's assigned configuration. - ### How this feature works Before performing any action in a pipeline stage, the plugin validates that the GitHub teams configured using the `impersonateGitHubTeam` feature are assigned with one of the following roles in GitHub: