-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathregen_service_deploy_entrypoints.py
More file actions
165 lines (147 loc) · 5.78 KB
/
regen_service_deploy_entrypoints.py
File metadata and controls
165 lines (147 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""
Regenerate per-service deploy-azd entrypoint workflows.
For each single-service entrypoint (deploy-azd-<svc>.yml that called the
now-deleted deploy-azd-service.yml reusable), write a fresh entrypoint that
calls deploy-azd.yml directly with the proven contract used by
deploy-azd-dev.yml:
- githubEnvironment: branch (so feature-branch service previews avoid the
protected 'dev' selected-branch restriction while still using the approved
environment-scoped OIDC subject).
- environment: dev (azd env name).
- skipProvision: true (per-service deploys never re-run provision).
- deployStatic/uiOnly: false (per-service entrypoints are backend-only).
- serviceFilter: <service-name> (scopes the core workflow to that one svc).
Output uses LF line endings to avoid the CRLF parser edge cases that caused
every run of every per-service entrypoint to emit `startup_failure` with no
jobs scheduled.
"""
from pathlib import Path
import re
import sys
WORKFLOWS_DIR = Path(".github/workflows")
# Match entrypoints like deploy-azd-<svc>.yml that referenced the reusable
# wrapper (deploy-azd-service.yml). Exclude orchestration files.
EXCLUDE = {
"deploy-azd.yml",
"deploy-azd-dev.yml",
"deploy-azd-prod.yml",
"deploy-azd-truth.yml", # scoped multi-service entrypoint, handled separately
"deploy-azd-service.yml", # already deleted
}
TEMPLATE = """name: deploy-azd-{svc} (entrypoint)
on:
push:
branches:
- main
paths:
- apps/{svc}/**
- lib/**
- azure.yaml
- .infra/**
- .kubernetes/**
- .github/workflows/deploy-azd.yml
- .github/workflows/deploy-azd-{svc}.yml
workflow_dispatch:
inputs:
location:
description: Azure location
required: true
default: centralus
projectName:
description: Project prefix used by naming convention
required: true
default: holidaypeakhub405
imageTag:
description: Image tag to deploy
required: true
default: latest
testedSourceSha:
description: Optional tested source commit SHA to deploy
required: false
default: ''
testedSourceRef:
description: Optional tested source ref to deploy when testedSourceSha is empty
required: false
default: ''
skipProvision:
description: Skip azd provision and reuse the current environment infrastructure
required: true
type: boolean
default: true
forceApimSync:
description: Force APIM sync and smoke checks even when no changed services are detected
required: true
type: boolean
default: true
autoAllowAcrRunnerIp:
description: Temporarily allow GitHub runner egress IP in ACR firewall during deploy
required: true
type: boolean
default: true
skipPromptGates:
description: Skip the prompt-sync CI gates (image prompt verification and Foundry instructions verification)
required: true
type: boolean
default: false
skipPostgresPreflight:
description: Skip the PostgreSQL password preflight probe (CRUD only; ignored for agent services)
required: true
type: boolean
default: false
permissions:
id-token: write
contents: write
concurrency:
group: deploy-azd-dev-{svc}
cancel-in-progress: false
jobs:
deploy:
permissions:
id-token: write
contents: write
issues: write
uses: ./.github/workflows/deploy-azd.yml
with:
environment: dev
githubEnvironment: branch
location: ${{{{ github.event_name == 'workflow_dispatch' && inputs.location || 'centralus' }}}}
projectName: ${{{{ github.event_name == 'workflow_dispatch' && inputs.projectName || 'holidaypeakhub405' }}}}
imageTag: ${{{{ github.event_name == 'workflow_dispatch' && inputs.imageTag || github.sha }}}}
sourceSha: ${{{{ github.event_name == 'workflow_dispatch' && inputs.testedSourceSha || github.sha }}}}
sourceRef: ${{{{ github.event_name == 'workflow_dispatch' && inputs.testedSourceRef || github.ref }}}}
deployStatic: false
uiOnly: false
apiBaseUrl: ''
deployChangedOnly: true
skipProvision: ${{{{ fromJSON(github.event_name == 'workflow_dispatch' && toJSON(inputs.skipProvision) || 'true') }}}}
serviceFilter: {svc}
forceApimSync: ${{{{ fromJSON(github.event_name == 'workflow_dispatch' && toJSON(inputs.forceApimSync) || 'true') }}}}
autoAllowAcrRunnerIp: ${{{{ fromJSON(github.event_name == 'workflow_dispatch' && toJSON(inputs.autoAllowAcrRunnerIp) || 'true') }}}}
skipApiSmokeChecks: false
skipPromptGates: ${{{{ fromJSON(github.event_name == 'workflow_dispatch' && toJSON(inputs.skipPromptGates) || 'false') }}}}
skipPostgresPreflight: ${{{{ fromJSON(github.event_name == 'workflow_dispatch' && toJSON(inputs.skipPostgresPreflight) || 'false') }}}}
secrets:
AZURE_CLIENT_ID: ${{{{ secrets.AZURE_CLIENT_ID }}}}
AZURE_TENANT_ID: ${{{{ secrets.AZURE_TENANT_ID }}}}
AZURE_SUBSCRIPTION_ID: ${{{{ secrets.AZURE_SUBSCRIPTION_ID }}}}
"""
def service_name_from_file(path: Path) -> str | None:
m = re.fullmatch(r"deploy-azd-(.+)\.yml", path.name)
return m.group(1) if m else None
def regenerate() -> list[Path]:
written: list[Path] = []
for path in sorted(WORKFLOWS_DIR.glob("deploy-azd-*.yml")):
if path.name in EXCLUDE:
continue
svc = service_name_from_file(path)
if not svc:
continue
content = TEMPLATE.format(svc=svc)
# Ensure LF-only line endings on disk.
path.write_bytes(content.replace("\r\n", "\n").encode("utf-8"))
written.append(path)
return written
if __name__ == "__main__":
for p in regenerate():
print(p)
print(f"TOTAL {len(regenerate())}", file=sys.stderr)