4545import java .nio .file .Paths ;
4646import java .time .Duration ;
4747import java .util .ArrayList ;
48+ import java .util .HashMap ;
4849import java .util .List ;
50+ import java .util .Map ;
4951import java .util .stream .Collectors ;
5052import java .util .stream .Stream ;
5153import org .apache .commons .lang3 .StringUtils ;
@@ -68,8 +70,7 @@ public class TemplatesReleaseMojo extends TemplatesBaseMojo {
6870
6971 private static final Logger LOG = LoggerFactory .getLogger (TemplatesReleaseMojo .class );
7072
71- private record Blueprint (String name , String path ) {}
72- ;
73+ private record ManifestEntry (String name , String path ) {}
7374
7475 private static final Gson GSON = new Gson ();
7576
@@ -193,6 +194,16 @@ private record Blueprint(String name, String path) {}
193194 required = false )
194195 protected String yamlManifestName ;
195196
197+ // Options directory for additional parameter files for yaml blueprints.
198+ // These files provide more context for jinja variables used in the yaml
199+ // blueprints.
200+ @ Parameter (
201+ defaultValue = "yaml/src/main/python/options" ,
202+ property = "yamlOptionsPath" ,
203+ readonly = true ,
204+ required = false )
205+ protected String yamlOptionsPath ;
206+
196207 public void execute () throws MojoExecutionException {
197208
198209 if (librariesBucketName == null || librariesBucketName .isEmpty ()) {
@@ -279,50 +290,38 @@ public void execute() throws MojoExecutionException {
279290 "Trying to upload Job Builder blueprints to bucket '{}'..." ,
280291 bucketNameOnly (bucketName ));
281292 Path yamlPath = Paths .get (project .getBasedir ().getAbsolutePath (), yamlBlueprintsPath );
282- if (!Files .exists (yamlPath ) || !Files .isDirectory (yamlPath )) {
283- LOG .warn ("YAML blueprints directory not found, skipping upload for path: " , yamlPath );
293+ Path yamlOptionsPath =
294+ Paths .get (project .getBasedir ().getAbsolutePath (), this .yamlOptionsPath );
295+
296+ if ((!Files .exists (yamlPath ) || !Files .isDirectory (yamlPath ))
297+ && (!Files .exists (yamlOptionsPath ) || !Files .isDirectory (yamlOptionsPath ))) {
298+ LOG .warn (
299+ "YAML blueprints {} and/or options directory {} not found, skipping upload for paths." ,
300+ yamlPath ,
301+ yamlOptionsPath );
284302 } else {
285303
286- try (Storage storage = StorageOptions .getDefaultInstance ().getService ();
287- Stream <Path > paths = Files .list (yamlPath )) {
288- List <Blueprint > blueprints = new ArrayList <>();
289- paths
290- .filter (
291- path ->
292- Files .isRegularFile (path )
293- && path .getFileName ().toString ().endsWith (".yaml" ))
294- .forEach (
295- path -> {
296- String fileName = path .getFileName ().toString ();
297- String objectName =
298- String .join ("/" , stagePrefix , yamlBlueprintsGCSPath , fileName );
299- BlobId blobId = BlobId .of (bucketNameOnly (bucketName ), objectName );
300-
301- BlobInfo blobInfo = BlobInfo .newBuilder (blobId ).build ();
302-
303- // Upload every blueprint with retries
304- Failsafe .with (gcsRetryPolicy ())
305- .run (
306- () -> {
307- try (InputStream inputStream = Files .newInputStream (path )) {
308- storage .create (blobInfo , inputStream );
309- }
310- });
311-
312- LOG .info (
313- "Uploaded blueprint {} to gs://{}/{}" ,
314- fileName ,
315- bucketNameOnly (bucketName ),
316- objectName );
317- blueprints .add (new Blueprint (fileName , objectName ));
318- });
304+ try (Storage storage = StorageOptions .getDefaultInstance ().getService ()) {
305+ List <ManifestEntry > blueprints = new ArrayList <>();
306+ List <ManifestEntry > options = new ArrayList <>();
307+
308+ // Upload the main Yaml blueprints
309+ uploadArtifacts (storage , yamlPath , "" , blueprints );
310+
311+ // Upload the jinja parameter option files
312+ uploadArtifacts (storage , yamlOptionsPath , "options" , options );
313+
314+ // Build the manifest file
319315 String manifestObjectName =
320316 String .join ("/" , stagePrefix , yamlBlueprintsGCSPath , yamlManifestName );
321317 BlobId manifestBlobId = BlobId .of (bucketNameOnly (bucketName ), manifestObjectName );
322318 BlobInfo manifestBlobInfo = BlobInfo .newBuilder (manifestBlobId ).build ();
323319
324320 // Upload the manifest file with retries
325- byte [] manifestBytes = GSON .toJson (blueprints ).getBytes (StandardCharsets .UTF_8 );
321+ Map <String , List <ManifestEntry >> manifestMap = new HashMap <>();
322+ manifestMap .put ("blueprints" , blueprints );
323+ manifestMap .put ("options" , options );
324+ byte [] manifestBytes = GSON .toJson (manifestMap ).getBytes (StandardCharsets .UTF_8 );
326325 Failsafe .with (gcsRetryPolicy ())
327326 .run (
328327 () ->
@@ -353,6 +352,50 @@ public void execute() throws MojoExecutionException {
353352 }
354353 }
355354
355+ private void uploadArtifacts (
356+ Storage storage , Path directory , String subFolder , List <ManifestEntry > entries )
357+ throws IOException {
358+ if (Files .exists (directory ) && Files .isDirectory (directory )) {
359+ try (Stream <Path > paths = Files .list (directory )) {
360+ paths
361+ .filter (
362+ path ->
363+ Files .isRegularFile (path ) && path .getFileName ().toString ().endsWith (".yaml" ))
364+ .forEach (
365+ path -> {
366+ String fileName = path .getFileName ().toString ();
367+ String objectName =
368+ subFolder .isEmpty ()
369+ ? String .join ("/" , stagePrefix , yamlBlueprintsGCSPath , fileName )
370+ : String .join (
371+ "/" , stagePrefix , yamlBlueprintsGCSPath , subFolder , fileName );
372+ uploadToGcs (storage , path , objectName );
373+ entries .add (new ManifestEntry (fileName , objectName ));
374+ });
375+ }
376+ }
377+ }
378+
379+ private void uploadToGcs (Storage storage , Path path , String objectName ) {
380+ BlobId blobId = BlobId .of (bucketNameOnly (bucketName ), objectName );
381+ BlobInfo blobInfo = BlobInfo .newBuilder (blobId ).build ();
382+
383+ // Upload every blueprint with retries
384+ Failsafe .with (gcsRetryPolicy ())
385+ .run (
386+ () -> {
387+ try (InputStream inputStream = Files .newInputStream (path )) {
388+ storage .create (blobInfo , inputStream );
389+ }
390+ });
391+
392+ LOG .info (
393+ "Uploaded file {} to gs://{}/{}" ,
394+ path .getFileName ().toString (),
395+ bucketNameOnly (bucketName ),
396+ objectName );
397+ }
398+
356399 private static <T > RetryPolicy <T > gcsRetryPolicy () {
357400 return RetryPolicy .<T >builder ()
358401 .handle (IOException .class )
0 commit comments