Skip to content

Commit fdf51e1

Browse files
authored
Merge pull request Azure#60 from Azure/image-to-ghcr
Simplify image creation for bicep module by pushing latest image to GHCR
2 parents a309457 + e1b94f5 commit fdf51e1

12 files changed

Lines changed: 355 additions & 127 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
name: Create and publish a Docker images for apps
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'TasksTracker.Processor.Backend.Svc/**'
9+
- 'TasksTracker.TasksManager.Backend.Api/**'
10+
- 'TasksTracker.WebPortal.Frontend.Ui/**'
11+
workflow_dispatch: {}
12+
13+
env:
14+
REGISTRY: ghcr.io
15+
BACKEND_API_IMAGE_NAME: azure/tasksmanager-backend-api
16+
FRONTEND_APP_IMAGE_NAME: azure/tasksmanager-frontend-webapp
17+
BACKEND_PROCESSOR_IMAGE_NAME: azure/tasksmanager-backend-processor
18+
19+
jobs:
20+
detect-changes:
21+
name: Detect apps which has changed to trigger image jobs conditionally
22+
runs-on: ubuntu-latest
23+
permissions:
24+
pull-requests: read
25+
outputs:
26+
backend: ${{ steps.filter.outputs.backend }}
27+
frontend: ${{ steps.filter.outputs.frontend }}
28+
processor: ${{ steps.filter.outputs.processor }}
29+
steps:
30+
- uses: actions/checkout@v3
31+
- uses: dorny/paths-filter@v2
32+
id: filter
33+
with:
34+
filters: |
35+
backend:
36+
- 'TasksTracker.TasksManager.Backend.Api/**'
37+
frontend:
38+
- 'TasksTracker.WebPortal.Frontend.Ui/**'
39+
processor:
40+
- 'TasksTracker.Processor.Backend.Svc/**'
41+
42+
build-and-push-backend-image:
43+
needs: detect-changes
44+
name: Build and push backend image
45+
if: ${{ needs.detect-changes.outputs.backend == 'true' }}
46+
runs-on: ubuntu-latest
47+
permissions:
48+
contents: read
49+
packages: write
50+
51+
steps:
52+
- name: Log in to the Container registry
53+
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
54+
with:
55+
registry: ${{ env.REGISTRY }}
56+
username: ${{ github.actor }}
57+
password: ${{ secrets.GITHUB_TOKEN }}
58+
59+
- name: Extract metadata (tags, labels) for Docker
60+
id: meta
61+
uses: docker/metadata-action@v4
62+
with:
63+
images: ${{ env.REGISTRY }}/${{ env.BACKEND_API_IMAGE_NAME }}
64+
tags: |
65+
type=raw,value=latest,enable={{is_default_branch}}
66+
type=ref,event=branch
67+
type=sha
68+
69+
- name: Build and push Docker image
70+
uses: docker/build-push-action@v4
71+
with:
72+
file: ./TasksTracker.TasksManager.Backend.Api/Dockerfile
73+
push: true
74+
tags: ${{ steps.meta.outputs.tags }}
75+
labels: ${{ steps.meta.outputs.labels }}
76+
77+
build-and-push-frontend-image:
78+
needs: detect-changes
79+
name: Build and push frontend image
80+
if: ${{ needs.detect-changes.outputs.frontend == 'true' }}
81+
runs-on: ubuntu-latest
82+
permissions:
83+
contents: read
84+
packages: write
85+
86+
steps:
87+
- name: Log in to the Container registry
88+
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
89+
with:
90+
registry: ${{ env.REGISTRY }}
91+
username: ${{ github.actor }}
92+
password: ${{ secrets.GITHUB_TOKEN }}
93+
94+
- name: Extract metadata (tags, labels) for Docker
95+
id: meta
96+
uses: docker/metadata-action@v4
97+
with:
98+
images: ${{ env.REGISTRY }}/${{ env.FRONTEND_APP_IMAGE_NAME }}
99+
tags: |
100+
type=raw,value=latest,enable={{is_default_branch}}
101+
type=ref,event=branch
102+
type=sha
103+
104+
- name: Build and push Docker image
105+
uses: docker/build-push-action@v4
106+
with:
107+
file: ./TasksTracker.WebPortal.Frontend.Ui/Dockerfile
108+
push: true
109+
tags: ${{ steps.meta.outputs.tags }}
110+
labels: ${{ steps.meta.outputs.labels }}
111+
112+
build-and-push-backend-processor-image:
113+
needs: detect-changes
114+
name: Build and push backend processor image
115+
if: ${{ needs.detect-changes.outputs.processor == 'true' }}
116+
runs-on: ubuntu-latest
117+
permissions:
118+
contents: read
119+
packages: write
120+
121+
steps:
122+
- name: Log in to the Container registry
123+
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
124+
with:
125+
registry: ${{ env.REGISTRY }}
126+
username: ${{ github.actor }}
127+
password: ${{ secrets.GITHUB_TOKEN }}
128+
129+
- name: Extract metadata (tags, labels) for Docker
130+
id: meta
131+
uses: docker/metadata-action@v4
132+
with:
133+
images: ${{ env.REGISTRY }}/${{ env.BACKEND_PROCESSOR_IMAGE_NAME }}
134+
tags: |
135+
type=raw,value=latest,enable={{is_default_branch}}
136+
type=ref,event=branch
137+
type=sha
138+
139+
- name: Build and push Docker image
140+
uses: docker/build-push-action@v4
141+
with:
142+
file: ./TasksTracker.Processor.Backend.Svc/Dockerfile
143+
push: true
144+
tags: ${{ steps.meta.outputs.tags }}
145+
labels: ${{ steps.meta.outputs.labels }}

TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@
1414
<PackageReference Include="SendGrid" Version="9.28.1" />
1515
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
1616
</ItemGroup>
17-
1817
</Project>

TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@
1414
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.1" />
1515
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
1616
</ItemGroup>
17-
1817
</Project>

TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,4 @@
1313
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.1" />
1414
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
1515
</ItemGroup>
16-
1716
</Project>

bicep/main.bicep

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,6 @@ param keyVaultName string = '${prefix}kv-${uniqueString(resourceGroup().id)}${su
100100
@description('The name of the container registry.')
101101
param containerRegistryName string
102102

103-
@description('The username of the container registry user.')
104-
param containerRegistryUsername string
105-
106-
@description('The password name of the container registry.')
107-
// We disable lint of this line as it is not a secret
108-
#disable-next-line secure-secrets-in-params
109-
param containerRegistryPasswordRefName string
110-
111-
@secure()
112-
param containerRegistryPassword string
113-
114103
@description('The image for the backend processor service.')
115104
param backendProcessorServiceImage string
116105

@@ -212,9 +201,6 @@ module containerApps 'modules/container-apps.bicep' = {
212201
backendApiServiceName: backendApiServiceName
213202
frontendWebAppServiceName: frontendWebAppServiceName
214203
containerAppsEnvironmentName: containerAppsEnvironmentName
215-
containerRegistryUsername: containerRegistryUsername
216-
containerRegistryPasswordRefName: containerRegistryPasswordRefName
217-
containerRegistryPassword: containerRegistryPassword
218204
keyVaultId: keyVault.outputs.keyVaultId
219205
serviceBusName: serviceBus.outputs.serviceBusName
220206
serviceBusTopicName: serviceBus.outputs.serviceBusTopicName

bicep/main.parameters.json

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,6 @@
6262
"containerRegistryName": {
6363
"value": "<CONTAINER_REGISTRY_NAME>"
6464
},
65-
"containerRegistryUsername": {
66-
"value": "<CONTAINER_REGISTRY_ADMIN>"
67-
},
68-
"containerRegistryPasswordRefName": {
69-
"value": "acaworkshopacrazurecrio-acaworkshopacr"
70-
},
71-
"containerRegistryPassword": {
72-
"value": "<CONTAINER_REGISTRY_PASSWORD>"
73-
},
7465
"backendProcessorServiceImage": {
7566
"value": "<CONTAINER_REGISTRY_NAME>.azurecr.io/tasksmanager/tasksmanager-backend-processor:latest"
7667
},

bicep/modules/container-apps.bicep

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,6 @@ param externalStorageAccountName string
6565
@description('The name of the container registry.')
6666
param containerRegistryName string
6767

68-
@description('The username of the container registry user.')
69-
param containerRegistryUsername string
70-
71-
// We disable lint of this line as it is not a secret
72-
#disable-next-line secure-secrets-in-params
73-
param containerRegistryPasswordRefName string
74-
75-
@secure()
76-
param containerRegistryPassword string
77-
7868
@description('The image for the backend api service.')
7969
param backendApiServiceImage string
8070

@@ -87,6 +77,9 @@ param frontendWebAppServiceImage string
8777
@description('The name of the application insights.')
8878
param applicationInsightsName string
8979

80+
var containerRegistryPullRoleGuid='7f951dda-4ed3-4680-a7ca-43fe172d538d'
81+
82+
9083
// ------------------
9184
// RESOURCES
9285
// ------------------
@@ -100,6 +93,26 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing
10093
name: applicationInsightsName
10194
}
10295

96+
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = {
97+
name: containerRegistryName
98+
}
99+
100+
resource containerRegistryUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
101+
name: 'aca-user-identity-${uniqueString(resourceGroup().id)}'
102+
location: location
103+
tags: tags
104+
}
105+
106+
resource containerRegistryPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if(!empty(containerRegistryName)) {
107+
name: guid(subscription().id, containerRegistry.id, containerRegistryUserAssignedIdentity.id)
108+
scope: containerRegistry
109+
properties: {
110+
principalId: containerRegistryUserAssignedIdentity.properties.principalId
111+
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', containerRegistryPullRoleGuid)
112+
principalType: 'ServicePrincipal'
113+
}
114+
}
115+
103116
module frontendWebAppService 'container-apps/webapp-frontend-service.bicep' = {
104117
name: 'frontendWebAppService-${uniqueString(resourceGroup().id)}'
105118
params: {
@@ -108,11 +121,10 @@ module frontendWebAppService 'container-apps/webapp-frontend-service.bicep' = {
108121
tags: tags
109122
containerAppsEnvironmentId: containerAppsEnvironment.id
110123
containerRegistryName: containerRegistryName
111-
containerRegistryUsername: containerRegistryUsername
112-
containerRegistryPasswordRefName: containerRegistryPasswordRefName
113-
containerRegistryPassword: containerRegistryPassword
124+
containerRegistryUserAssignedIdentityId: containerRegistryUserAssignedIdentity.id
114125
frontendWebAppServiceImage: frontendWebAppServiceImage
115126
appInsightsInstrumentationKey: applicationInsights.properties.InstrumentationKey
127+
116128
}
117129
}
118130

@@ -126,9 +138,7 @@ module backendApiService 'container-apps/webapi-backend-service.bicep' = {
126138
serviceBusName: serviceBusName
127139
serviceBusTopicName: serviceBusTopicName
128140
containerRegistryName: containerRegistryName
129-
containerRegistryUsername: containerRegistryUsername
130-
containerRegistryPasswordRefName: containerRegistryPasswordRefName
131-
containerRegistryPassword: containerRegistryPassword
141+
containerRegistryUserAssignedIdentityId: containerRegistryUserAssignedIdentity.id
132142
backendApiServiceImage: backendApiServiceImage
133143
cosmosDbName: cosmosDbName
134144
cosmosDbDatabaseName: cosmosDbDatabaseName
@@ -149,9 +159,7 @@ module backendProcessorService 'container-apps/processor-backend-service.bicep'
149159
serviceBusTopicName: serviceBusTopicName
150160
serviceBusTopicAuthorizationRuleName: serviceBusTopicAuthorizationRuleName
151161
containerRegistryName: containerRegistryName
152-
containerRegistryUsername: containerRegistryUsername
153-
containerRegistryPasswordRefName: containerRegistryPasswordRefName
154-
containerRegistryPassword: containerRegistryPassword
162+
containerRegistryUserAssignedIdentityId: containerRegistryUserAssignedIdentity.id
155163
sendGridKeySecretName: sendGridKeySecretName
156164
sendGridKeySecretValue: sendGridKeySecretValue
157165
externalStorageAccountName: externalStorageAccountName

bicep/modules/container-apps/processor-backend-service.bicep

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,8 @@ param externalStorageAccountName string
5454
@description('The name of the container registry.')
5555
param containerRegistryName string
5656

57-
@description('The username of the container registry user.')
58-
param containerRegistryUsername string
59-
60-
@description('The password name of the container registry.')
61-
// We disable lint of this line as it is not a secret
62-
#disable-next-line secure-secrets-in-params
63-
param containerRegistryPasswordRefName string
64-
65-
@secure()
66-
param containerRegistryPassword string
57+
@description('The resource ID of the user assigned managed identity for the container registry to be able to pull images from it.')
58+
param containerRegistryUserAssignedIdentityId string
6759

6860
@description('The image for the backend processor service.')
6961
param backendProcessorServiceImage string
@@ -106,7 +98,10 @@ resource backendProcessorService 'Microsoft.App/containerApps@2022-06-01-preview
10698
location: location
10799
tags: tags
108100
identity: {
109-
type: 'SystemAssigned'
101+
type: 'SystemAssigned,UserAssigned'
102+
userAssignedIdentities: {
103+
'${containerRegistryUserAssignedIdentityId}': {}
104+
}
110105
}
111106
properties: {
112107
managedEnvironmentId: containerAppsEnvironmentId
@@ -129,18 +124,13 @@ resource backendProcessorService 'Microsoft.App/containerApps@2022-06-01-preview
129124
name: 'appinsights-key'
130125
value: appInsightsInstrumentationKey
131126
}
132-
{
133-
name: containerRegistryPasswordRefName
134-
value: containerRegistryPassword
135-
}
136127
]
137-
registries: [
128+
registries: !empty(containerRegistryName) ? [
138129
{
139130
server: '${containerRegistryName}.azurecr.io'
140-
username: containerRegistryUsername
141-
passwordSecretRef: containerRegistryPasswordRefName
131+
identity: containerRegistryUserAssignedIdentityId
142132
}
143-
]
133+
] : []
144134
}
145135
template: {
146136
containers: [

0 commit comments

Comments
 (0)