Skip to content

Commit 1b9cd06

Browse files
committed
fix: validate token source values in publish workflow template
1 parent 01f44e5 commit 1b9cd06

2 files changed

Lines changed: 49 additions & 7 deletions

File tree

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

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,51 @@ ${autoDeployComment}
4949
tenant-id: \${{ secrets.AZURE_TENANT_ID }}
5050
subscription-id: \${{ secrets.AZURE_SUBSCRIPTION_ID }}
5151
52+
- name: Validate token source values (${env})
53+
env:
54+
AVAILABLE_SECRETS_JSON: \${{ toJSON(secrets) }}
55+
run: |
56+
missing=0
57+
tokens=$(grep -o '{#\\[[^]]*\\]#}' configuration.${env}.yaml | sed -E 's/^\\{#\\[([^]]+)\\]#\\}$/\\1/' | sort -u || true)
58+
59+
if [ -z "$tokens" ]; then
60+
echo "No tokens found in configuration.${env}.yaml"
61+
exit 0
62+
fi
63+
64+
while IFS= read -r token; do
65+
if [ -z "$token" ]; then
66+
continue
67+
fi
68+
69+
if ! echo "$token" | grep -Eq '^[A-Za-z_][A-Za-z0-9_]*$'; then
70+
echo "::error::Token '$token' is not a valid environment variable name. Use letters, numbers, and underscores only."
71+
missing=1
72+
continue
73+
fi
74+
75+
value=$(jq -r --arg token "$token" '.[$token] // empty' <<< "$AVAILABLE_SECRETS_JSON")
76+
if [ -z "$value" ]; then
77+
echo "::error::Missing secret for token '$token'"
78+
missing=1
79+
continue
80+
fi
81+
82+
printf '%s=%s\\n' "$token" "$value" >> "$GITHUB_ENV"
83+
done <<< "$tokens"
84+
85+
if [ "$missing" -ne 0 ]; then
86+
exit 1
87+
fi
88+
5289
- name: Substitute tokens in configuration.${env}.yaml
5390
uses: cschleiden/replace-tokens@v1.3
5491
with:
5592
tokenPrefix: '{#['
5693
tokenSuffix: ']#}'
5794
files: '["configuration.${env}.yaml"]'
58-
# Example token mapping for ${env} (uncomment and customize when needed):
59-
# env:
60-
# MY_SECRET: \${{ secrets.MY_SECRET_${envUpper} }}
61-
# ANOTHER_TOKEN: \${{ secrets.ANOTHER_TOKEN_${envUpper} }}
95+
# Token values are injected in the previous step based on token names.
96+
# Ensure tokens in configuration.${env}.yaml match secret names exactly.
6297
6398
- name: Validate token substitution (${env})
6499
run: |

tests/unit/templates/github-actions/publish-workflow.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ describe('github-actions/publish-workflow', () => {
241241
artifactDir: './apim-artifacts',
242242
environments: ['dev', 'prod'],
243243
});
244+
expect(workflow).toContain('Validate token source values (dev)');
245+
expect(workflow).toContain('Validate token source values (prod)');
246+
expect(workflow).toContain('AVAILABLE_SECRETS_JSON: ${{ toJSON(secrets) }}');
247+
expect(workflow).toContain("echo \"::error::Missing secret for token '$token'\"");
248+
expect(workflow).toContain("printf '%s=%s\\n' \"$token\" \"$value\" >> \"$GITHUB_ENV\"");
244249
expect(workflow).toContain('Validate token substitution (dev)');
245250
expect(workflow).toContain('Validate token substitution (prod)');
246251
expect(workflow).toContain("grep -q '{#\\[' configuration.dev.yaml");
@@ -252,11 +257,13 @@ describe('github-actions/publish-workflow', () => {
252257
artifactDir: './apim-artifacts',
253258
environments: ['dev'],
254259
});
260+
const validateSourcesIdx = workflow.indexOf('Validate token source values (dev)');
255261
const substituteIdx = workflow.indexOf('cschleiden/replace-tokens');
256-
const validateIdx = workflow.indexOf('Validate token substitution (dev)');
262+
const validateSubstitutionIdx = workflow.indexOf('Validate token substitution (dev)');
257263
const publishIdx = workflow.indexOf('npx apiops publish');
258-
expect(substituteIdx).toBeLessThan(validateIdx);
259-
expect(validateIdx).toBeLessThan(publishIdx);
264+
expect(validateSourcesIdx).toBeLessThan(substituteIdx);
265+
expect(substituteIdx).toBeLessThan(validateSubstitutionIdx);
266+
expect(validateSubstitutionIdx).toBeLessThan(publishIdx);
260267
});
261268
});
262269
});

0 commit comments

Comments
 (0)