Skip to content

Commit 389e37e

Browse files
committed
streaming publish pipeline/workflow
1 parent fa94b13 commit 389e37e

2 files changed

Lines changed: 124 additions & 133 deletions

File tree

src/templates/github-actions/publish-workflow.ts

Lines changed: 85 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Licensed under the MIT license.
33
/**
44
* GitHub Actions publish workflow template
5-
* Push-to-main trigger with commit ID choice, environment selection, and multi-env stages
5+
* Push-to-main trigger with commit ID choice and a single parameterized publish
6+
* job driven by a workflow-level environment variable (TARGET_ENV)
67
*/
78

89
export interface PublishWorkflowConfig {
@@ -11,22 +12,58 @@ export interface PublishWorkflowConfig {
1112
}
1213

1314
export function generatePublishWorkflow(config: PublishWorkflowConfig): string {
15+
const defaultEnvironment = config.environments[0] ?? 'dev';
1416
const envChoices = config.environments.map((env) => ` - ${env}`).join('\n');
1517

16-
const envJobs = config.environments.map((env, idx) => {
17-
const envUpper = env.toUpperCase();
18-
const autoDeployComment = idx === 0
19-
? ` # To enable automatic deployment on push to main, uncomment the condition below:
20-
# if: github.event.inputs.ENVIRONMENT == '${env}' || github.event_name == 'push'`
21-
: ` # To enable automatic deployment on push to main, uncomment the condition below:
22-
# if: github.event.inputs.ENVIRONMENT == '${env}' || github.event_name == 'push'
23-
# And change needs to: needs: [get-commit, publish-${config.environments[idx - 1]}]`;
24-
25-
return ` publish-${env}:
26-
${autoDeployComment}
27-
if: github.event.inputs.ENVIRONMENT == '${env}'
18+
return `name: Run APIM Publisher
19+
20+
on:
21+
push:
22+
branches:
23+
- main
24+
paths:
25+
- '${config.artifactDir}/**'
26+
- 'configuration.*.yaml'
27+
workflow_dispatch:
28+
inputs:
29+
COMMIT_ID_CHOICE:
30+
description: 'Choose "publish-all-artifacts-in-repo" only when you want to force republishing all artifacts (e.g. after build failure). Otherwise stick with the default behavior of "publish-artifacts-in-last-commit"'
31+
required: true
32+
type: choice
33+
default: publish-artifacts-in-last-commit
34+
options:
35+
- publish-artifacts-in-last-commit
36+
- publish-all-artifacts-in-repo
37+
ENVIRONMENT:
38+
description: 'Choose which environment to publish to'
39+
required: true
40+
type: choice
41+
default: ${defaultEnvironment}
42+
options:
43+
${envChoices}
44+
45+
permissions:
46+
id-token: write
47+
contents: read
48+
49+
# A single workflow-level variable selects the target environment. On manual runs
50+
# it comes from the ENVIRONMENT input; on push to main it defaults to '${defaultEnvironment}'.
51+
env:
52+
TARGET_ENV: \${{ github.event.inputs.ENVIRONMENT || '${defaultEnvironment}' }}
53+
54+
jobs:
55+
get-commit:
2856
runs-on: ubuntu-latest
29-
environment: ${env}
57+
outputs:
58+
commit_id: \${{ steps.commit.outputs.commit_id }}
59+
steps:
60+
- name: Set the Commit Id
61+
id: commit
62+
run: echo "commit_id=\${GITHUB_SHA}" >> $GITHUB_OUTPUT
63+
64+
publish:
65+
runs-on: ubuntu-latest
66+
environment: \${{ github.event.inputs.ENVIRONMENT || '${defaultEnvironment}' }}
3067
needs: get-commit
3168
steps:
3269
- name: Checkout repository
@@ -42,22 +79,29 @@ ${autoDeployComment}
4279
- name: Install dependencies
4380
run: npm install
4481
82+
- name: Resolve target environment
83+
id: env
84+
run: |
85+
echo "name=\${TARGET_ENV}" >> "$GITHUB_OUTPUT"
86+
echo "upper=\$(echo "\${TARGET_ENV}" | tr '[:lower:]' '[:upper:]')" >> "$GITHUB_OUTPUT"
87+
4588
- name: Azure Login (Federated Credential)
4689
uses: azure/login@v2
4790
with:
4891
client-id: \${{ secrets.AZURE_CLIENT_ID }}
4992
tenant-id: \${{ secrets.AZURE_TENANT_ID }}
5093
subscription-id: \${{ secrets.AZURE_SUBSCRIPTION_ID }}
5194
52-
- name: Validate token source values (${env})
95+
- name: Validate token source values
5396
env:
5497
AVAILABLE_SECRETS_JSON: \${{ toJSON(secrets) }}
5598
run: |
5699
missing=0
57-
tokens=$(grep -o '{#\\[[^]]*\\]#}' configuration.${env}.yaml | sed -E 's/^\\{#\\[([^]]+)\\]#\\}$/\\1/' | sort -u || true)
100+
config_file="configuration.\${TARGET_ENV}.yaml"
101+
tokens=$(grep -o '{#\\[[^]]*\\]#}' "$config_file" | sed -E 's/^\\{#\\[([^]]+)\\]#\\}$/\\1/' | sort -u || true)
58102
59103
if [ -z "$tokens" ]; then
60-
echo "No tokens found in configuration.${env}.yaml"
104+
echo "No tokens found in $config_file"
61105
exit 0
62106
fi
63107
@@ -86,111 +130,67 @@ ${autoDeployComment}
86130
exit 1
87131
fi
88132
89-
- name: Substitute tokens in configuration.${env}.yaml
133+
- name: Substitute tokens in configuration file
90134
uses: cschleiden/replace-tokens@v1.3
91135
with:
92136
tokenPrefix: '{#['
93137
tokenSuffix: ']#}'
94-
files: '["configuration.${env}.yaml"]'
138+
files: '["configuration.\${{ env.TARGET_ENV }}.yaml"]'
95139
# Token values are injected in the previous step based on token names.
96-
# Ensure tokens in configuration.${env}.yaml match secret names exactly.
140+
# Ensure tokens in the configuration file match secret names exactly.
97141
98-
- name: Validate token substitution (${env})
142+
- name: Validate token substitution
99143
run: |
100-
if grep -q '{#\\[' configuration.${env}.yaml; then
101-
echo "Unresolved tokens remain in configuration.${env}.yaml"
102-
grep -o '{#\\[[^]]*\\]#}' configuration.${env}.yaml | sort -u
144+
config_file="configuration.\${TARGET_ENV}.yaml"
145+
if grep -q '{#\\[' "$config_file"; then
146+
echo "Unresolved tokens remain in $config_file"
147+
grep -o '{#\\[[^]]*\\]#}' "$config_file" | sort -u
103148
exit 1
104149
fi
105150
106-
- name: Dry-run validation (${env}, incremental)
151+
- name: Dry-run validation (incremental)
107152
if: \${{ github.event.inputs.COMMIT_ID_CHOICE != 'publish-all-artifacts-in-repo' }}
108153
run: |
109154
npx apiops publish \\
110155
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
111-
--resource-group \${{ secrets.APIM_RESOURCE_GROUP_${envUpper} }} \\
112-
--service-name \${{ secrets.APIM_SERVICE_NAME_${envUpper} }} \\
156+
--resource-group \${{ secrets[format('APIM_RESOURCE_GROUP_{0}', steps.env.outputs.upper)] }} \\
157+
--service-name \${{ secrets[format('APIM_SERVICE_NAME_{0}', steps.env.outputs.upper)] }} \\
113158
--source ${config.artifactDir} \\
114-
--overrides configuration.${env}.yaml \\
159+
--overrides configuration.\${{ env.TARGET_ENV }}.yaml \\
115160
--commit-id \${{ needs.get-commit.outputs.commit_id }} \\
116161
--dry-run
117162
118-
- name: Dry-run validation (${env}, all artifacts)
163+
- name: Dry-run validation (all artifacts)
119164
if: \${{ github.event.inputs.COMMIT_ID_CHOICE == 'publish-all-artifacts-in-repo' }}
120165
run: |
121166
npx apiops publish \\
122167
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
123-
--resource-group \${{ secrets.APIM_RESOURCE_GROUP_${envUpper} }} \\
124-
--service-name \${{ secrets.APIM_SERVICE_NAME_${envUpper} }} \\
168+
--resource-group \${{ secrets[format('APIM_RESOURCE_GROUP_{0}', steps.env.outputs.upper)] }} \\
169+
--service-name \${{ secrets[format('APIM_SERVICE_NAME_{0}', steps.env.outputs.upper)] }} \\
125170
--source ${config.artifactDir} \\
126-
--overrides configuration.${env}.yaml \\
171+
--overrides configuration.\${{ env.TARGET_ENV }}.yaml \\
127172
--dry-run
128173
129-
- name: Publish to ${env} (incremental - last commit only)
174+
- name: Publish (incremental - last commit only)
130175
if: \${{ github.event.inputs.COMMIT_ID_CHOICE != 'publish-all-artifacts-in-repo' }}
131176
run: |
132177
npx apiops publish \\
133178
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
134-
--resource-group \${{ secrets.APIM_RESOURCE_GROUP_${envUpper} }} \\
135-
--service-name \${{ secrets.APIM_SERVICE_NAME_${envUpper} }} \\
179+
--resource-group \${{ secrets[format('APIM_RESOURCE_GROUP_{0}', steps.env.outputs.upper)] }} \\
180+
--service-name \${{ secrets[format('APIM_SERVICE_NAME_{0}', steps.env.outputs.upper)] }} \\
136181
--source ${config.artifactDir} \\
137-
--overrides configuration.${env}.yaml \\
182+
--overrides configuration.\${{ env.TARGET_ENV }}.yaml \\
138183
--commit-id \${{ needs.get-commit.outputs.commit_id }}
139184
140-
- name: Publish to ${env} (all artifacts)
185+
- name: Publish (all artifacts)
141186
if: \${{ github.event.inputs.COMMIT_ID_CHOICE == 'publish-all-artifacts-in-repo' }}
142187
run: |
143188
npx apiops publish \\
144189
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
145-
--resource-group \${{ secrets.APIM_RESOURCE_GROUP_${envUpper} }} \\
146-
--service-name \${{ secrets.APIM_SERVICE_NAME_${envUpper} }} \\
190+
--resource-group \${{ secrets[format('APIM_RESOURCE_GROUP_{0}', steps.env.outputs.upper)] }} \\
191+
--service-name \${{ secrets[format('APIM_SERVICE_NAME_{0}', steps.env.outputs.upper)] }} \\
147192
--source ${config.artifactDir} \\
148-
--overrides configuration.${env}.yaml
149-
`;
150-
}).join('\n');
151-
152-
return `name: Run APIM Publisher
153-
154-
on:
155-
push:
156-
branches:
157-
- main
158-
paths:
159-
- '${config.artifactDir}/**'
160-
- 'configuration.*.yaml'
161-
workflow_dispatch:
162-
inputs:
163-
COMMIT_ID_CHOICE:
164-
description: 'Choose "publish-all-artifacts-in-repo" only when you want to force republishing all artifacts (e.g. after build failure). Otherwise stick with the default behavior of "publish-artifacts-in-last-commit"'
165-
required: true
166-
type: choice
167-
default: publish-artifacts-in-last-commit
168-
options:
169-
- publish-artifacts-in-last-commit
170-
- publish-all-artifacts-in-repo
171-
ENVIRONMENT:
172-
description: 'Choose which environment to publish to'
173-
required: true
174-
type: choice
175-
default: ${config.environments[0]}
176-
options:
177-
${envChoices}
178-
179-
permissions:
180-
id-token: write
181-
contents: read
182-
183-
jobs:
184-
get-commit:
185-
runs-on: ubuntu-latest
186-
outputs:
187-
commit_id: \${{ steps.commit.outputs.commit_id }}
188-
steps:
189-
- name: Set the Commit Id
190-
id: commit
191-
run: echo "commit_id=\${GITHUB_SHA}" >> $GITHUB_OUTPUT
192-
193-
${envJobs}
193+
--overrides configuration.\${{ env.TARGET_ENV }}.yaml
194194
`;
195195
}
196196

0 commit comments

Comments
 (0)