Skip to content

Commit 0a2a2ca

Browse files
committed
README: elaborate on registering the GitHub App
Now that I am trying to establish support for projects other than Git, I need to register a new GitHub App. Let's document that process better for the next person who wants to repeat that feat. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent efdaee3 commit 0a2a2ca

File tree

1 file changed

+59
-18
lines changed

1 file changed

+59
-18
lines changed

README.md

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,50 +45,91 @@ Finally, [run the Function locally](https://learn.microsoft.com/en-us/azure/azur
4545

4646
You can also run/debug it via VS Code, there is a default configuration called "Attach to Node Functions".
4747

48-
## How this GitHub App was set up
48+
## How to set up this GitHub App
4949

5050
This process looks a bit complex, the main reason for that being that three things have to be set up essentially simultaneously: an Azure Function, a GitHub repository and a GitHub App.
5151

5252
### The Azure Function
5353

54-
First of all, a new [Azure Function](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Web%2Fsites/kind/functionapp) was created. A Linux one was preferred, for cost and performance reasons. Deployment with GitHub was _not_ yet configured.
54+
First of all, a new [Azure Function](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Web%2Fsites/kind/functionapp) needs to be created. A Linux one is preferred, with a regular Consumption plan, for [cost](https://azure.microsoft.com/en-us/pricing/details/functions/) and performance reasons. Deployment with GitHub should _not_ yet be configured.
5555

5656
#### Obtaining the Azure credentials
5757

58-
The idea is to use [Role-Based Access Control (RBAC)](https://github.com/Azure/functions-action?tab=readme-ov-file#using-azure-service-principal-for-rbac-as-deployment-credential) to log into Azure in the deploy workflow. Essentially, after the deployment succeeded, in an Azure CLI (for example [the one that is very neatly embedded in the Azure Portal](https://learn.microsoft.com/en-us/azure/cloud-shell/get-started/classic)), run this (after replacing the placeholders `{subscription-id}`, `{resource-group}` and `{app-name}`):
58+
The idea is to use [OpenID Connect](https://docs.github.com/en/actions/concepts/security/openid-connect) to log into Azure in the deploy workflow, _identifying_ as said workflow, via a "Managed Identity". This can be registered after the Azure Function has been successfully created: In an Azure CLI (for example [the one that is very neatly embedded in the Azure Portal](https://learn.microsoft.com/en-us/azure/cloud-shell/get-started/classic)), run this (after replacing the placeholders `{subscription-id}`, `{resource-group}` and `{app-name}`):
5959

6060
```shell
61-
az ad sp create-for-rbac --name "myApp" --role contributor \
62-
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name} \
63-
--sdk-auth
61+
az identity create --name <managed-identity-name> -g <resource-group>
62+
az identity federated-credential create \
63+
--identity-name <managed-identity-name> \
64+
--resource-group <resource-group> \
65+
--name github-workflow \
66+
--issuer https://token.actions.githubusercontent.com \
67+
--subject repo:<org>/gitgitgadget-github-app:ref:refs/heads/main \
68+
--audiences api://AzureADTokenExchange
69+
# The scope can be copied from the Azure Portal URL after navigating to the Azure Function
70+
az role assignment create \
71+
--assignee <client-id-of-managed-identity> \
72+
--scope '/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<azure-function-name>' \
73+
--role 'Contributor'
6474
```
6575

66-
The result is called an "Azure Service Principal" in Azure Speak; Essentially it is a tightly-scoped credential that allows deploying this particular Azure Function and that's it. This Azure Service Principal will be the value of the `AZURE_RBAC_CREDENTIALS` Actions secret, more on that below.
76+
The result is a "managed identity", essentially a tightly-scoped credential that allows deploying this particular Azure Function from that particular repository in a GitHub workflow run and that's it. This managed identity is identified via the `AZURE_CLIENT_ID`, `AZURE_TENANT_ID` and `AZURE_SUBSCRIPTION_ID` Actions secrets, more on that below.
6777

6878
#### Some environment variables
6979

70-
A few environment variables will have to be configured for use with the Azure Function. This can be done on the "Configuration" tab, which is in the "Settings" group.
80+
A few environment variables need to be configured for use with the Azure Function. This can be done on the "Configuration" tab, which is in the "Settings" group.
7181

72-
Concretely, the environment variables `GITHUB_WEBHOOK_SECRET` and `GITGITGADGET_TRIGGER_TOKEN` (a Personal Access Token to trigger the Azure Pipelines) need to be set. For the first, a generated random string was used. The second one was [created](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows#create-a-pat) scoped to the Azure DevOps project `gitgitgadget` with the Build (read & execute) permissions.
82+
Concretely, the environment variables `GITHUB_WEBHOOK_SECRET` needs to be set, any generated random string can be used as its value (and the same value needs to be used when eventually registering the actual GitHub App).
7383

74-
Also, the `GITHUB_APP_ID` and `GITHUB_APP_PRIVATE_KEY` variables are needed in order to trigger GitHub workflow runs. These were obtained as part of registering the GitHub App.
84+
Also, the `GITHUB_APP_ID` and `GITHUB_APP_PRIVATE_KEY` variables are needed in order to trigger GitHub workflow runs. These are obtained as part of registering the GitHub App (see below).
7585

7686
### The repository
7787

78-
On https://github.com/, the `+` link on the top was pressed, and an empty, private repository was registered. Nothing was pushed to it yet.
88+
Create a fork of https://github.com/gitgitgadget/gitgitgadget-github-app. Configure the Azure Managed Identity via Actions secrets, under the keys `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and `AZURE_SUBSCRIPTION_ID`. Also, the `AZURE_FUNCTION_NAME` secret needs to be defined (its value is the name of the Azure Function).
7989

80-
After that, the Azure Service Principal needs to be registered as Actions secret, under the name `AZURE_RBAC_CREDENTIALS`.
90+
Also configure the repository _variable_ `DEPLOY_WITH_WORKFLOWS`; Its value must correspond to the fork of https://github.com/gitgitgadget/gitgitgadget-workflows, in the form `<org>/gitgitgadget-workflows`. Note that that fork _must_ have a valid project configuration in its `CONFIG` repository variable.
8191

82-
This repository was initialized locally by forking https://github.com/gitgitgadget/gitgitgadget and separating out the Azure Functions part of it. Then, the test suite was developed and the GitHub workflows were adapted from https://github.com/git-for-windows/gfw-helper-github-app. After that, the `origin` remote was set to the newly registered repository on GitHub.
83-
84-
As a last step, the repository was pushed, triggering the deployment to the Azure Function.
92+
As a last step, on the Actions tab, the `Deploy to Azure` workflow needs to be triggered manually, which deploys the Azure Function.
8593

8694
### The GitHub App
8795

88-
Finally, the existing GitHub App's webhook URL was redirected to the new one. If there had not been an existing GitHub App, [a new GitHub App would have been registered](https://github.com/settings/apps/new) with https://github.com/gitgitgadget as homepage URL.
96+
Now it is finally time to [register a new GitHub App](https://github.com/settings/apps/new) with https://github.com/<org>> as homepage URL.
8997

90-
As Webhook URL, the URL of the Azure Function was used, which can be copied in the "Functions" tab of the Azure Function. It looks similar to this: https://my-github-app.azurewebsites.net/api/MyGitHubApp
98+
As Webhook URL, use the URL of the Azure Function, which should look like this: https://<azure-function-name>.azurewebsites.net/api/GitGitGadget
9199

92100
The value stored in the Azure Function as `GITHUB_WEBHOOK_SECRET` was used as Webhook secret.
93101

94-
The GitGitGadget GitHub app requires the following permissions: Read access to metadata, and Read and write access to checks, code, commit statuses, issues, pull requests, and workflows.
102+
The GitGitGadget GitHub app requires the following permissions: Read access to metadata, and Read and write access to Actions, Checks, Commit statuses, Contents, Issues, Pull requests, and Workflows. It needs the following webhook events to be enabled: Check run, Commit comment, Issue comment, Pull request, Pull request review, Pull request review comment, Push, Repository, and Status.
103+
104+
Once the GitHub App is successfully registered (and unfortunately only then), the private key can be generated via clicking the `Generate a private key` button in the "Private keys" section toward the bottom. This will automatically download a file; The contents of that file, with newlines replaced by `\n`, need to be configured as `GITHUB_APP_PRIVATE_KEY` environment variable in your Azure Function's `Settings>Environment variables` tab, and `GITHUB_APP_ID` needs to be set, too (it can be seen on the GitHub App's page at the top, labeled as "App ID").
105+
106+
#### Using `register-github-app-cli`
107+
108+
A convenient alternative to clicky-clicky in the GitHub UI to register the GitHub is the convenient [`npx register-github-app-cli` command](https://github.com/gr2m/register-github-app-cli): Use it with `--org <owning-organization>` and a variation of this manifest:
109+
110+
```yml
111+
name: <name>
112+
url: https://github.com/apps/<name>
113+
hook_attributes:
114+
url: https://<function-app-name>.azurewebsites.net/api/GitGitGadget
115+
public: false
116+
default_permissions:
117+
actions: write
118+
checks: write
119+
commit_statuses: write
120+
contents: write
121+
issues: write
122+
metadata: read
123+
pull_requests: write
124+
workflows: write
125+
default_events:
126+
- check_run
127+
- commit_comment
128+
- issue_comment
129+
- pull_request
130+
- pull_request_review
131+
- pull_request_review_comment
132+
- push
133+
- repository
134+
- status
135+
```

0 commit comments

Comments
 (0)