@@ -212,6 +212,7 @@ jobs:
212212 metaImages : ${{ steps.set.outputs.metaImages }}
213213 sign : ${{ steps.set.outputs.sign }}
214214 privateRepo : ${{ steps.set.outputs.privateRepo }}
215+ secretIds : ${{ steps.set.outputs.secretIds }}
215216 ghaCacheSign : ${{ steps.set.outputs.ghaCacheSign }}
216217 steps :
217218 -
@@ -522,6 +523,16 @@ jobs:
522523 const match = value.match(/^target:(.+)$/);
523524 return match ? match[1] : undefined;
524525 };
526+ const parseSecretId = secret => {
527+ if (typeof secret === 'string') {
528+ const idAttr = secret.split(',').map(attr => attr.trim()).find(attr => attr.startsWith('id='));
529+ return idAttr ? idAttr.substring(3) : undefined;
530+ }
531+ if (secret && typeof secret === 'object' && typeof secret.id === 'string') {
532+ return secret.id;
533+ }
534+ return undefined;
535+ };
525536 const resolveTarget = () => {
526537 if (targetDefs[inpTarget]) {
527538 return inpTarget;
@@ -550,6 +561,11 @@ jobs:
550561 if (unsupportedTargets.length > 0) {
551562 throw new Error(`Only one target can be built at once, found unsupported targets: ${unsupportedTargets.join(', ')}`);
552563 }
564+ const secretIds = {};
565+ for (const name of allowedTargets) {
566+ secretIds[name] = (targetDefs[name]?.secret || []).map(parseSecretId).filter(Boolean);
567+ }
568+ core.setOutput('secretIds', JSON.stringify(secretIds));
553569 });
554570 } catch (error) {
555571 core.setFailed(error);
@@ -836,6 +852,7 @@ jobs:
836852 INPUT_CACHE-SCOPE : ${{ inputs.cache-scope }}
837853 INPUT_CACHE-MODE : ${{ inputs.cache-mode }}
838854 INPUT_BUILD-SECRETS : ${{ secrets.build-secrets }}
855+ INPUT_SECRET-IDS : ${{ needs.prepare.outputs.secretIds }}
839856 INPUT_CONTEXT : ${{ inputs.context }}
840857 INPUT_FILES : ${{ inputs.files }}
841858 INPUT_OUTPUT : ${{ inputs.output }}
@@ -878,6 +895,7 @@ jobs:
878895 const inpCacheScope = core.getInput('cache-scope');
879896 const inpCacheMode = core.getInput('cache-mode');
880897 const inpBuildSecrets = core.getInput('build-secrets');
898+ const inpSecretIds = core.getInput('secret-ids');
881899 const inpContext = core.getInput('context');
882900 const inpFiles = Util.getInputList('files');
883901 const inpOutput = core.getInput('output');
@@ -901,6 +919,7 @@ jobs:
901919 tags: inpMetaTags
902920 };
903921 const renderTemplate = value => Util.compileHandlebars(value, {noEscape: true}, {meta});
922+
904923 const parseBuildSecrets = value => {
905924 const normalized = value.trim();
906925 if (!normalized) {
@@ -950,6 +969,19 @@ jobs:
950969 }
951970 return secrets;
952971 };
972+
973+ const validateBuildSecrets = (secrets, secretIds) => {
974+ for (const {target, id} of secrets) {
975+ const targetSecretIds = secretIds[target];
976+ if (!targetSecretIds) {
977+ throw new Error(`Build secret target "${target}" is not part of the resolved Bake definition`);
978+ }
979+ if (!Array.isArray(targetSecretIds) || !targetSecretIds.includes(id)) {
980+ throw new Error(`Build secret "${id}" must be declared in Bake target "${target}" before it can be provided through build-secrets`);
981+ }
982+ }
983+ };
984+
953985 const toBuildSecretEnvName = (id, index) => `BUILD_SECRET_${index}_${id.toUpperCase().replace(/[^A-Z0-9_]/g, '_')}`;
954986
955987 const gitContextAttrs = GitHub.context.ref.startsWith('refs/tags/') ? {checksum: GitHub.context.sha} : {'fetch-by-commit': 'true'};
@@ -977,7 +1009,16 @@ jobs:
9771009 core.setFailed(err.message);
9781010 return;
9791011 }
980-
1012+
1013+ let secretIds;
1014+ try {
1015+ secretIds = JSON.parse(inpSecretIds || '{}');
1016+ validateBuildSecrets(buildSecrets, secretIds);
1017+ } catch (err) {
1018+ core.setFailed(err.message);
1019+ return;
1020+ }
1021+
9811022 const envs = Object.assign({},
9821023 inpVars ? inpVars.reduce((acc, curr) => {
9831024 const idx = curr.indexOf('=');
0 commit comments