Skip to content

Commit 61448cd

Browse files
👷 Add Reusable Workflows; Instructions (#2)
* test deployment * remove azd * add env * try with env * change envs * test client ID * typpo * new env to fix ERROR: getting target resource: getting default resource groups for environment: dev: resource not found: 0 resource groups with prefix or suffix with value: 'dev' * add env * update readme * add reusable workflows * add env back * add envs * add path for testing * try as secrets * fix expression error * fix more envs * try with env at step * add env s * fix the env name * clean up * add env back * clean up * Remove tests; more cleanup * add bicep as resusable * remove redundant info * improve docs * enable azd for non self hosted runners
1 parent 306a866 commit 61448cd

File tree

5 files changed

+224
-102
lines changed

5 files changed

+224
-102
lines changed
Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
1-
name: Validate bicep scripts
1+
name: Validate Bicep Scripts Backend Integration
2+
23
on:
34
workflow_dispatch:
45
push:
56
branches:
67
- main
78
paths:
89
- 'backend-integration/**'
10+
- '.github/workflows/lib-azure-bicep-validation.yml'
911

1012
# Use concurrency to ensure that only a single job or workflow using the same concurrency group will run at a time
1113
concurrency:
1214
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
1315
cancel-in-progress: true # Cancel previously queued jobs and run the latest
1416

15-
1617
jobs:
17-
build:
18-
timeout-minutes: 10
19-
runs-on: ubuntu-latest
20-
steps:
21-
- name: Checkout
22-
uses: actions/checkout@v2
23-
24-
- name: Azure CLI script
25-
uses: azure/[email protected]
26-
with:
27-
inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f backend-integration/infra/main.bicep
28-
29-
- name: Log in with Azure (Federated Credentials)
30-
if: ${{ env.AZURE_CLIENT_ID != '' }}
31-
run: |
32-
azd auth login \
33-
--client-id "$AZURE_CLIENT_ID" \
34-
--federated-credential-provider "github" \
35-
--tenant-id "$AZURE_TENANT_ID"
18+
backend-integration-validation:
19+
uses: ./.github/workflows/lib-azure-bicep-validation.yml
20+
with:
21+
work-dir: backend-integration
22+
secrets:
23+
SELF_HOSTED_RUNNER_TOKEN: ${{ secrets.SELF_HOSTED_RUNNER_TOKEN }}

‎.github/workflows/backend-integration-azure-deploy.yml‎

Lines changed: 12 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,8 @@ on:
77
- main
88
paths:
99
- 'backend-integration/**'
10+
- '.github/workflows/backend-integration-azure-deploy.yml'
1011

11-
# GitHub Actions workflow to deploy to Azure using azd
12-
# To configure required secrets for connecting to Azure, simply run `azd pipeline config`
13-
14-
# Set up permissions for deploying with secretless Azure federated credentials
15-
# https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication
16-
permissions:
17-
id-token: write
18-
contents: read
1912

2013
# Use concurrency to ensure that only a single job or workflow using the same concurrency group will run at a time
2114
concurrency:
@@ -24,76 +17,14 @@ concurrency:
2417

2518

2619
jobs:
27-
self-hosted-status:
28-
runs-on: ubuntu-latest
29-
timeout-minutes: 5
30-
outputs:
31-
runner-status: ${{ steps.runnerstatus.outputs.status }}
32-
steps:
33-
- name: Check runner status
34-
id: runnerstatus
35-
uses: SatelCreative/[email protected]
36-
with:
37-
github-runner-token: ${{ secrets.SELF_HOSTED_RUNNER_TOKEN }} #Should have access to manage runner
38-
org-name: SatelCreative
39-
build:
40-
needs: [self-hosted-status]
41-
timeout-minutes: 10
42-
runs-on: ${{ contains(needs.self-hosted-status.outputs.runner-status, 'online') && 'self-hosted' || 'ubuntu-latest' }}
43-
environment: dev
44-
env:
45-
AZURE_CLIENT_ID: ${{ vars.BACKEND_INTEGRATION_CLIENT_ID }}
46-
AZURE_TENANT_ID: ${{ vars.BACKEND_INTEGRATION_TENANT_ID }}
47-
AZURE_SUBSCRIPTION_ID: ${{ vars.BACKEND_INTEGRATION_SUBSCRIPTION_ID }}
48-
AZURE_CREDENTIALS: ${{ secrets.BACKEND_INTEGRATION_CREDENTIALS }}
49-
steps:
50-
- name: Checkout
51-
uses: actions/checkout@v4
52-
53-
- name: Install azd
54-
uses: Azure/[email protected]
55-
56-
- name: Log in with Azure (Federated Credentials)
57-
if: ${{ env.AZURE_CLIENT_ID != '' }}
58-
run: |
59-
azd auth login \
60-
--client-id "$AZURE_CLIENT_ID" \
61-
--federated-credential-provider "github" \
62-
--tenant-id "$AZURE_TENANT_ID"
63-
64-
65-
- name: Log in with Azure (Client Credentials)
66-
if: ${{ env.AZURE_CREDENTIALS != '' }}
67-
run: |
68-
$info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable;
69-
Write-Host "::add-mask::$($info.clientSecret)"
70-
71-
azd auth login \
72-
--client-id "$($info.clientId)" \
73-
--client-secret "$($info.clientSecret)" \
74-
--tenant-id "$($info.tenantId)"
75-
76-
env:
77-
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
78-
79-
# Commented out to preserve existing application settings
80-
# Uncomment when infrastructure changes are needed
81-
#- name: Provision Infrastructure
82-
# run: |
83-
# cd backend-integration
84-
# azd provision --no-prompt
85-
# env:
86-
# AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
87-
# AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
88-
# AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
89-
90-
- name: Deploy Application
91-
run:
92-
|
93-
cd backend-integration
94-
azd deploy --no-prompt
95-
env:
96-
AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
97-
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
98-
AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
99-
20+
backend-integration-dev:
21+
uses: ./.github/workflows/lib-azure-deploy.yml
22+
with:
23+
work-dir: backend-integration
24+
environment: ${{ vars.BACKEND_INTEGRATION_ENV_NAME }}
25+
secrets:
26+
SELF_HOSTED_RUNNER_TOKEN: ${{ secrets.SELF_HOSTED_RUNNER_TOKEN }}
27+
AZURE_CLIENT_ID: ${{ vars.BACKEND_INTEGRATION_CLIENT_ID }}
28+
AZURE_TENANT_ID: ${{ vars.BACKEND_INTEGRATION_TENANT_ID }}
29+
AZURE_SUBSCRIPTION_ID: ${{ vars.BACKEND_INTEGRATION_SUBSCRIPTION_ID }}
30+
AZURE_LOCATION: ${{ vars.BACKEND_INTEGRATION_LOCATION }}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Validate Bicep Scripts
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
work-dir:
7+
required: true
8+
type: string
9+
10+
secrets:
11+
SELF_HOSTED_RUNNER_TOKEN:
12+
required: true
13+
14+
jobs:
15+
self-hosted-status:
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 5
18+
outputs:
19+
runner-status: ${{ steps.runnerstatus.outputs.status }}
20+
steps:
21+
- name: Check runner status
22+
id: runnerstatus
23+
uses: SatelCreative/[email protected]
24+
with:
25+
github-runner-token: ${{ secrets.SELF_HOSTED_RUNNER_TOKEN }} #Should have access to manage runner
26+
org-name: SatelCreative
27+
28+
validate-bicep:
29+
timeout-minutes: 10
30+
needs: [self-hosted-status]
31+
runs-on: ${{ contains(needs.self-hosted-status.outputs.runner-status, 'online') && 'self-hosted' || 'ubuntu-latest' }}
32+
steps:
33+
- name: Checkout
34+
uses: actions/checkout@v4
35+
36+
- name: Azure CLI script
37+
uses: azure/[email protected]
38+
with:
39+
inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f ${{ inputs.work-dir }}/infra/main.bicep
40+
41+
- name: Log in with Azure (Federated Credentials)
42+
if: ${{ env.AZURE_CLIENT_ID != '' }}
43+
run: |
44+
azd auth login \
45+
--client-id "$AZURE_CLIENT_ID" \
46+
--federated-credential-provider "github" \
47+
--tenant-id "$AZURE_TENANT_ID"
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Deploys to Azure Function App
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
work-dir:
7+
required: true
8+
type: string
9+
environment:
10+
required: true
11+
type: string
12+
13+
secrets:
14+
SELF_HOSTED_RUNNER_TOKEN:
15+
required: true
16+
AZURE_CLIENT_ID:
17+
required: true
18+
AZURE_TENANT_ID:
19+
required: true
20+
AZURE_SUBSCRIPTION_ID:
21+
required: true
22+
AZURE_LOCATION:
23+
required: true
24+
25+
permissions:
26+
id-token: write
27+
contents: read
28+
29+
jobs:
30+
self-hosted-status:
31+
runs-on: ubuntu-latest
32+
timeout-minutes: 5
33+
outputs:
34+
runner-status: ${{ steps.runnerstatus.outputs.status }}
35+
steps:
36+
- name: Check runner status
37+
id: runnerstatus
38+
uses: SatelCreative/[email protected]
39+
with:
40+
github-runner-token: ${{ secrets.SELF_HOSTED_RUNNER_TOKEN }} #Should have access to manage runner
41+
org-name: SatelCreative
42+
43+
build-and-deploy:
44+
needs: [self-hosted-status]
45+
timeout-minutes: 10
46+
runs-on: ${{ contains(needs.self-hosted-status.outputs.runner-status, 'online') && 'self-hosted' || 'ubuntu-latest' }}
47+
environment: ${{ inputs.environment }}
48+
env:
49+
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
50+
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
51+
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
52+
AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
53+
steps:
54+
- name: Checkout
55+
uses: actions/checkout@v4
56+
57+
- name: Install azd
58+
if: ${{ runner.os == 'Linux' && runner.name == 'GitHub Actions' }}
59+
uses: Azure/[email protected]
60+
61+
- name: Log in with Azure (Federated Credentials)
62+
if: ${{ env.AZURE_CLIENT_ID != '' }}
63+
run: |
64+
echo "Using client ID: $AZURE_CLIENT_ID"
65+
azd auth login \
66+
--client-id "$AZURE_CLIENT_ID" \
67+
--federated-credential-provider "github" \
68+
--tenant-id "$AZURE_TENANT_ID"
69+
70+
# Commented out to preserve existing application settings
71+
# Uncomment when infrastructure changes are needed
72+
#- name: Provision Infrastructure
73+
# run: |
74+
# cd ${{ inputs.work-dir }}
75+
# azd provision --no-prompt
76+
77+
78+
- name: Deploy Application
79+
run: |
80+
cd ${{ inputs.work-dir }}
81+
azd env new $AZURE_ENV_NAME --location $AZURE_LOCATION --subscription $AZURE_SUBSCRIPTION_ID --no-prompt
82+
azd deploy --no-prompt

‎howto.md‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,80 @@ cd shopify-integration/
141141
azd up
142142
```
143143

144+
145+
## Azure DevOps Setup
146+
147+
### Prerequisites
148+
149+
Before setting up Azure DevOps integration, you'll need to gather the following information:
150+
151+
- **Azure Subscription ID**: Found in the [Azure Portal Subscriptions page](https://portal.azure.com/#view/Microsoft_Azure_Billing/SubscriptionsBladeV2)
152+
- **Azure Tenant ID**: Available after app registration
153+
- **Azure Client ID**: Generated during app registration
154+
155+
### Step-by-Step Setup
156+
157+
#### 1. Get Azure Subscription ID
158+
159+
Navigate to the [Azure Portal Subscriptions page](https://portal.azure.com/#view/Microsoft_Azure_Billing/SubscriptionsBladeV2) and copy your subscription ID.
160+
161+
#### 2. Register Azure Application
162+
163+
1. Go to the [Azure App Registrations page](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
164+
2. Click **"New registration"**
165+
3. Provide a name for your application
166+
4. Select the appropriate account types
167+
5. Click **"Register"**
168+
169+
This will provide you with:
170+
- **AZURE_CLIENT_ID** (Application ID)
171+
- **AZURE_TENANT_ID** (Directory ID)
172+
173+
#### 3. Configure Federated Credentials
174+
175+
1. In your app registration, navigate to **"Certificates & secrets"**
176+
2. Click on **"Federated credentials"** tab
177+
3. Click **"Add credential"**
178+
4. Configure the federated credential with:
179+
- **Entity type**: GitHub Actions
180+
- **Repository**: `your-org/your-repo`
181+
- **Environment**: `backend-integration-dev` (must match your workflow environment)
182+
- **Branch**: `main` (or your default branch)
183+
184+
> **Important**: The environment name must match exactly with the environment specified in your GitHub workflows. See the [workflow configuration](https://github.com/SatelCreative/azure-function-app-boilerplate/blob/4149c2b6f838b8b2b9ad6a091120674572347ad1/.github/workflows/backend-integration-azure-deploy.yml#L46-L47) for reference.
185+
186+
#### 4. Assign Contributor Role
187+
188+
The registered app needs contributor permissions for your Azure subscription. Run the following command locally:
189+
190+
```bash
191+
az role assignment create \
192+
--assignee "AZURE_CLIENT_ID" \
193+
--role "Contributor" \
194+
--scope "/subscriptions/AZURE_SUBSCRIPTION_ID"
195+
```
196+
197+
**Verification**: To verify the role assignment, run:
198+
199+
```bash
200+
az role assignment list \
201+
--assignee "AZURE_CLIENT_ID" \
202+
--scope "/subscriptions/AZURE_SUBSCRIPTION_ID" \
203+
--output table
204+
```
205+
206+
> **Note**: Make sure you're logged into the correct Azure organization before running these commands.
207+
208+
### Environment Variables
209+
210+
Once the app has been created on Azure, you'll need to add the following environment variables to your GitHub repository variables/secrets:
211+
212+
- `<APP_NAME>_CLIENT_ID`
213+
- `<APP_NAME>_TENANT_ID`
214+
- `<APP_NAME>_SUBSCRIPTION_ID`
215+
- `<APP_NAME>_ENV_NAME`
216+
- `<APP_NAME>_LOCATION`
217+
144218
This boilerplate provides a production-ready foundation for building Azure
145219
Function-based integrations with proper monitoring, deployment pipelines, and
146220
infrastructure management.

0 commit comments

Comments
 (0)