@leverege/build-tools 2.93.0-beta.10 → 2.93.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.93.0-beta.10",
3
+ "version": "2.93.0-beta.11",
4
4
  "description": "A collection of build / support tools for Leverege developers",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -1,7 +1,8 @@
1
- import crypto from 'crypto'
2
1
  import fs from 'fs'
3
2
 
4
- class ArtifactPusher {
3
+ import { toExplicitPath } from './Utils.mjs'
4
+
5
+ class ArtifactPuller {
5
6
  constructor( artifact ) {
6
7
  this.artifact = artifact
7
8
  }
@@ -11,11 +12,137 @@ class ArtifactPusher {
11
12
  }
12
13
  }
13
14
 
14
- class GenericArtifactPusher extends ArtifactPusher {
15
+ class GenericArtifactPuller extends ArtifactPuller {
16
+
17
+ async downloadFile( remoteFilePath, localFilePath ) {
18
+ const command = `gcloud artifacts generic download \
19
+ --project=${this.artifact.gcp_project_id} \
20
+ --location=${this.artifact.gcp_location} \
21
+ --repository=${this.artifact.gcp_artifact_registry_repository_name} \
22
+ --package=${this.artifact.gcp_artifact_registry_package_name} \
23
+ --version=${this.artifact.gcp_artifact_registry_package_version} \
24
+ --name="${remoteFilePath}" \
25
+ --destination=/tmp`
26
+
27
+ const oldPath = `/tmp/${remoteFilePath.split( '/' ).pop()}`
28
+ const newPath = localFilePath
29
+
30
+ // if file exists in the old path, delete it
31
+ if ( fs.existsSync( oldPath ) ) {
32
+ fs.unlinkSync( oldPath )
33
+ }
34
+
35
+ // if file exists in the new path, delete it
36
+ if ( fs.existsSync( newPath ) ) {
37
+ fs.unlinkSync( newPath )
38
+ }
39
+
40
+ // Ensure the directory exists
41
+ fs.mkdirSync( localFilePath.split( '/' ).slice( 0, -1 ).join( '/' ), { recursive : true } )
42
+
43
+ console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
44
+
45
+ const { execSync } = await import( 'child_process' )
46
+ const result = execSync( command, { encoding : 'utf8', stdio : 'pipe' } )
47
+ console.log( 'Result:', result )
48
+
49
+ // Check if file exists in the old path
50
+ if ( !fs.existsSync( oldPath ) ) {
51
+ console.error( `File does not exist in the old path: ${oldPath}` )
52
+ return false
53
+ }
54
+
55
+ console.log( `Copying file from ${oldPath} to ${newPath}` )
56
+
57
+ await fs.copyFileSync( oldPath, newPath )
58
+
59
+ // Check if file exists in the new path
60
+ if ( !fs.existsSync( newPath ) ) {
61
+ console.error( `File does not exist in the new path: ${newPath}` )
62
+ return false
63
+ }
64
+
65
+ return true
66
+ }
67
+
68
+ async downloadDirectory( localPath ) {
69
+ const command = `gcloud artifacts generic download \
70
+ --project=${this.artifact.gcp_project_id} \
71
+ --location=${this.artifact.gcp_location} \
72
+ --repository=${this.artifact.gcp_artifact_registry_repository_name} \
73
+ --package=${this.artifact.gcp_artifact_registry_package_name} \
74
+ --version=${this.artifact.gcp_artifact_registry_package_version} \
75
+ --destination=${localPath}`
76
+
77
+ console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
78
+
79
+ const { execSync } = await import( 'child_process' )
80
+ execSync( command, { encoding : 'utf8', stdio : 'pipe' } )
81
+
82
+ return true
83
+ }
84
+
85
+ async downloadNestedDirectory( remotePath, localPath ) {
86
+ const files = await this.listFiles( remotePath )
87
+ await Promise.all(
88
+ files
89
+ .filter( file => file.name.split( ':' ).pop().replaceAll( '%2F', '/' ).startsWith( remotePath ) )
90
+ .map( async ( file ) => {
91
+ const remoteFilePath = file.name.split( ':' ).pop().replaceAll( '%2F', '/' )
92
+ const localFilePath = `${localPath}${remoteFilePath.replaceAll( remotePath, '' )}`
93
+ await this.downloadFile( remoteFilePath, localFilePath )
94
+ } )
95
+ )
96
+ return true
97
+ }
98
+
99
+ async listFiles( ) {
100
+ const command = `gcloud artifacts files list \
101
+ --project=${this.artifact.gcp_project_id} \
102
+ --location=${this.artifact.gcp_location} \
103
+ --repository=${this.artifact.gcp_artifact_registry_repository_name} \
104
+ --package=${this.artifact.gcp_artifact_registry_package_name} \
105
+ --version ${this.artifact.gcp_artifact_registry_package_version} \
106
+ --format="json"`
107
+
108
+ console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
109
+
110
+ const { execSync } = await import( 'child_process' )
111
+ const result = execSync( command, { encoding : 'utf8', stdio : 'pipe' } )
112
+
113
+ // Parse the JSON response
114
+ const files = JSON.parse( result )
115
+
116
+ return files
117
+ }
15
118
 
16
119
  async pull() {
17
- throw new Error( 'Not implemented' )
120
+ console.log( 'Pulling artifact from registry...' )
121
+
122
+ if ( this.artifact.remote_file_path && this.artifact.local_file_path ) {
123
+ return this.downloadFile( this.artifact.remote_file_path, toExplicitPath( this.artifact.local_file_path ) )
124
+ }
125
+ if ( this.artifact.remote_file_path && this.artifact.local_path ) {
126
+ return this.downloadFile( this.artifact.remote_file_path, toExplicitPath( `${this.artifact.local_path}/${this.artifact.remote_file_path.split( '/' ).pop()}` ) )
127
+ }
128
+ if ( this.artifact.remote_path && this.artifact.local_path ) {
129
+ return this.downloadNestedDirectory( this.artifact.remote_path, toExplicitPath( this.artifact.local_path ) )
130
+ }
131
+ if ( this.artifact.remote_path && !this.artifact.local_path && !this.artifact.local_file_path ) {
132
+ return this.downloadDirectory( this.artifact.remote_path, '.' )
133
+ }
134
+ if ( !this.artifact.remote_path && !this.artifact.remote_file_path && this.artifact.local_path ) {
135
+ return this.downloadDirectory( toExplicitPath( this.artifact.local_path ) )
136
+ }
137
+ // if ( !this.artifact.remote_path && !this.artifact.remote_file_path && this.local_file_path ) {
138
+ // throw new Error( '' )
139
+ // }
140
+ // if ( this.artifact.remote_path && this.artifact.local_file_path ) {
141
+ // throw new Error( '' )
142
+ // }
143
+
144
+ return false
18
145
  }
19
146
  }
20
147
 
21
- export { ArtifactPusher, GenericArtifactPusher }
148
+ export { ArtifactPuller, GenericArtifactPuller }
@@ -1,25 +1,7 @@
1
- import crypto from 'crypto'
2
- import fs from 'fs'
3
-
4
1
  class ArtifactPusher {
5
2
  constructor( artifact ) {
6
3
  this.artifact = artifact
7
4
  }
8
-
9
- calculateHash() {
10
- try {
11
- const hash = crypto.createHash( 'sha256' )
12
- hash.update( fs.readFileSync( this.artifact.source_path ) )
13
- return hash.digest( 'base64url' )
14
- } catch ( error ) {
15
- console.error( error )
16
- throw new Error( `Failed to calculate hash for artifact ${this.artifact.name}: ${error.message}` )
17
- }
18
- }
19
-
20
- async exists() {
21
- throw new Error( 'Not implemented' )
22
- }
23
5
 
24
6
  async push() {
25
7
  throw new Error( 'Not implemented' )
@@ -28,68 +10,30 @@ class ArtifactPusher {
28
10
 
29
11
  class GenericArtifactPusher extends ArtifactPusher {
30
12
 
31
- async exists() {
32
- const isDirectory = fs.statSync( this.artifact.source_path ).isDirectory()
33
-
34
- // If source path is a directory, check whether the destination path alreadu exists in the registry
35
- if ( isDirectory ) {
36
- // For the time being, return false, and let gcloud skip existing files in upload-time.
37
- // It's pretty slow, might be worth to break down the directory into individual artifacts
38
- // and manage each one with its own pusher.
39
- return false
40
- }
41
-
42
- // Check if artifact already exists in the registry
43
- console.log( 'Checking if artifact already exists in the registry...' )
44
-
45
- const artifactHash = this.calculateHash()
46
-
13
+ async listFiles( ) {
47
14
  const command = `gcloud artifacts files list \
48
- --project=${this.artifact.gcp_project_id} \
49
- --location=${this.artifact.gcp_location} \
50
- --repository=${this.artifact.gcp_artifact_registry_repository_name} \
51
- --package=${this.artifact.gcp_artifact_registry_package_name} \
52
- --version ${this.artifact.gcp_artifact_registry_package_version} \
53
- --filter="name:${this.artifact.destination_path}" \
54
- --format="json"`
15
+ --project=${this.artifact.gcp_project_id} \
16
+ --location=${this.artifact.gcp_location} \
17
+ --repository=${this.artifact.gcp_artifact_registry_repository_name} \
18
+ --package=${this.artifact.gcp_artifact_registry_package_name} \
19
+ --version ${this.artifact.gcp_artifact_registry_package_version} \
20
+ --format="json"`
55
21
 
56
22
  console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
57
-
58
- try {
59
- const { execSync } = await import( 'child_process' )
60
- const result = execSync( command, { encoding : 'utf8', stdio : 'pipe' } )
23
+
24
+ const { execSync } = await import( 'child_process' )
25
+ const result = execSync( command, { encoding : 'utf8', stdio : 'pipe' } )
26
+
27
+ // Parse the JSON response
28
+ const files = JSON.parse( result )
61
29
 
62
- // Parse the JSON response
63
- const files = JSON.parse( result )
64
-
65
- // Check if any files were found and match our hash
66
- if ( files && files.length > 0 ) {
67
- for ( const file of files ) {
68
- for ( const hash of file.hashes ) {
69
- // Compare without padding since base64url may omit trailing '='
70
- const normalizedOurHash = artifactHash.replace( /=+$/, '' )
71
- const normalizedRegistryHash = hash.value.replace( /=+$/, '' )
72
- if ( hash.type === 'SHA256' && normalizedRegistryHash === normalizedOurHash ) {
73
- console.log( `Artifact already exists in the registry: ${this.artifact.gcp_artifact_registry_package_name}:${this.artifact.gcp_artifact_registry_package_version}` )
74
- return true
75
- }
76
- }
77
- }
78
- }
79
- console.log( 'Artifact does not exist in the registry' )
80
- return false
81
-
82
- } catch ( error ) {
83
- console.error( 'Error checking artifact existence:', error.message )
84
- throw error
85
- }
30
+ return files
86
31
  }
87
32
 
88
33
  async push() {
89
- console.log( 'Publishing artifact to registry...' )
34
+ console.log( 'Pushing artifact to registry...' )
90
35
 
91
- if ( await this.exists() ) {
92
- console.log( 'Artifact already exists in the registry' )
36
+ if ( this.artifact.remote_file_path ) {
93
37
  return false
94
38
  }
95
39
 
@@ -104,18 +48,19 @@ class GenericArtifactPusher extends ArtifactPusher {
104
48
  --package=${this.artifact.gcp_artifact_registry_package_name} \
105
49
  --version=${this.artifact.gcp_artifact_registry_package_version}`
106
50
 
107
- const isDirectory = fs.statSync( this.artifact.source_path ).isDirectory()
108
- if ( isDirectory ) {
109
- command += ` --source-directory=${this.artifact.source_path}`
51
+ if ( this.artifact.local_path ) {
52
+ command += ` --source-directory=${this.artifact.local_path}`
110
53
  command += ' --skip-existing'
111
- } else {
112
- command += ` --source=${this.artifact.source_path}`
54
+ } else if ( this.artifact.local_file_path ) {
55
+ const files = await this.listFiles( this.artifact.remote_path )
56
+ if ( files.some( file => file.name.split( ':' ).pop().replaceAll( '%2F', '/' ) === `${this.artifact.remote_path}/${this.artifact.remote_file_path.split( '/' ).pop()}` ) ) {
57
+ return false
58
+ }
59
+ command += ` --source=${this.artifact.local_file_path}`
113
60
  }
114
61
 
115
- if ( this.artifact.destination_path ) {
116
- command += ` --destination-path=${this.artifact.destination_path}`
117
- }
118
-
62
+ command += ` --destination-path=${this.artifact.remote_path}`
63
+
119
64
  console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
120
65
 
121
66
  try {
@@ -1,4 +1,4 @@
1
- import { assign, object, string, array, optional, enums, union } from 'superstruct'
1
+ import { assign, object, string, array, optional, enums, union, refine } from 'superstruct'
2
2
 
3
3
  const ArtifactTypeEnum = {
4
4
  GENERIC : 'generic',
@@ -25,16 +25,44 @@ const ArtifactSchema = assign( PartialArtifactSchema, object( {
25
25
  gcp_artifact_registry_package_version : string()
26
26
  } ) )
27
27
 
28
- const PartialGenericArtifactSchema = assign( PartialArtifactSchema, object( {
29
- type : enums( [ ArtifactTypeEnum.GENERIC ] ),
30
- source_path : string(),
31
- destination_path : string()
32
- } ) )
28
+ const PartialGenericArtifactSchema = refine(
29
+ assign( PartialArtifactSchema, object( {
30
+ type : enums( [ ArtifactTypeEnum.GENERIC ] ),
31
+ local_file_path : optional( string() ),
32
+ local_path : optional( string() ),
33
+ remote_file_path : optional( string() ),
34
+ remote_path : optional( string() )
35
+ } ) ),
36
+ 'ConflictingPaths',
37
+ ( value ) => {
38
+ if ( value.local_file_path && value.local_path ) {
39
+ return 'Only one of local_file_path or local_path must be provided'
40
+ }
41
+ if ( value.remote_file_path && value.remote_path ) {
42
+ return 'Only one of remote_file_path or remote_path must be provided'
43
+ }
44
+ return true
45
+ }
46
+ )
33
47
 
34
- const GenericArtifactSchema = assign( ArtifactSchema, object( {
35
- source_path : string(),
36
- destination_path : optional( string() )
37
- } ) )
48
+ const GenericArtifactSchema = refine(
49
+ assign( ArtifactSchema, object( {
50
+ local_file_path : optional( string() ),
51
+ local_path : optional( string() ),
52
+ remote_file_path : optional( string() ),
53
+ remote_path : optional( string() )
54
+ } ) ),
55
+ 'ConflictingPaths',
56
+ ( value ) => {
57
+ if ( value.local_file_path && value.local_path ) {
58
+ return 'Only one of local_file_path or local_path must be provided'
59
+ }
60
+ if ( value.remote_file_path && value.remote_path ) {
61
+ return 'Only one of remote_file_path or remote_path must be provided'
62
+ }
63
+ return true
64
+ }
65
+ )
38
66
 
39
67
  // Superstruct schema for defaults configuration
40
68
  const DefaultsSchema = object( {
@@ -1,3 +1,6 @@
1
+ import fs from 'fs'
2
+ import crypto from 'crypto'
3
+
1
4
  import { validate } from 'superstruct'
2
5
 
3
6
  import { parseYamlFile, warning } from '../Utils.mjs'
@@ -46,4 +49,65 @@ const flattenArtifactsSchema = ( artifactsSchema ) => {
46
49
  }, [] )
47
50
  }
48
51
 
49
- export { getArtifactsSchema, flattenArtifactsSchema }
52
+ const toImplicitPath = ( path ) => {
53
+ let implicitPath = path
54
+ // Remove leading './' if present
55
+ if ( implicitPath.startsWith( './' ) ) {
56
+ implicitPath = implicitPath.slice( 2 )
57
+ }
58
+ // Remove trailing slash
59
+ implicitPath = implicitPath.replace( /\/+$/, '' )
60
+ return implicitPath
61
+ }
62
+
63
+ const toExplicitPath = ( path ) => {
64
+ let explicitPath = path
65
+ // Keep absolute paths and paths already starting with '.' as-is
66
+ if ( !path.startsWith( '/' ) && !path.startsWith( '.' ) ) {
67
+ // Add './' to relative paths
68
+ explicitPath = `./${explicitPath}`
69
+ }
70
+ return explicitPath
71
+ }
72
+
73
+ const buildGenericArtifactName = ( artifact ) => {
74
+ const baseElements = [
75
+ 'projects',
76
+ artifact.gcp_project_id,
77
+ 'locations',
78
+ artifact.gcp_location,
79
+ 'repositories',
80
+ artifact.gcp_artifact_registry_repository_name,
81
+ 'files',
82
+ artifact.gcp_artifact_registry_package_name,
83
+ ]
84
+
85
+ const versionElement = artifact.gcp_artifact_registry_package_version
86
+
87
+ const remotePathElements = []
88
+
89
+ if ( artifact.remote_path || artifact.remote_file_path ) {
90
+ const explicitRemotePath = toExplicitPath( artifact.remote_path || artifact.remote_file_path )
91
+ const implicitRemotePath = toImplicitPath( explicitRemotePath )
92
+ if ( implicitRemotePath !== '.' ) {
93
+ remotePathElements.push( implicitRemotePath )
94
+ }
95
+ }
96
+
97
+ const name = [ baseElements.join( '/' ), versionElement, encodeURIComponent( remotePathElements.join( '/' ) ) ].join( ':' )
98
+
99
+ return name
100
+ }
101
+
102
+ const calculateHash = ( path ) => {
103
+ try {
104
+ const hash = crypto.createHash( 'sha256' )
105
+ hash.update( fs.readFileSync( path ) )
106
+ return hash.digest( 'base64url' )
107
+ } catch ( error ) {
108
+ console.error( error )
109
+ throw new Error( `Failed to calculate hash for artifact ${path}: ${error.message}` )
110
+ }
111
+ }
112
+
113
+ export { calculateHash, getArtifactsSchema, flattenArtifactsSchema, toImplicitPath, toExplicitPath, buildGenericArtifactName }
@@ -1,7 +1,68 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { warning } from '../Utils.mjs'
4
+
5
+ import { getArtifactsSchema, flattenArtifactsSchema } from './Utils.mjs'
6
+ import { ArtifactTypeEnum } from './Structs.mjs'
7
+ import { GenericArtifactPuller } from './ArtifactPuller.mjs'
8
+
3
9
  async function main() {
4
- return null
10
+
11
+ let artifactsYmlPath = null
12
+ let artifactName = null
13
+ let artifactPackageName = null
14
+ let artifactPackageVersion = null
15
+ let filteredArtifactSchema = null
16
+
17
+ if ( process.argv.length === 3 ) {
18
+ artifactsYmlPath = process.argv[2]
19
+ filteredArtifactSchema = await getArtifactsSchema( artifactsYmlPath )
20
+ const flattenedArtifactsSchema = flattenArtifactsSchema( filteredArtifactSchema )
21
+ filteredArtifactSchema = flattenedArtifactsSchema
22
+ } else if ( process.argv.length === 4 ) {
23
+ artifactsYmlPath = process.argv[2]
24
+ filteredArtifactSchema = await getArtifactsSchema( artifactsYmlPath )
25
+ const flattenedArtifactsSchema = flattenArtifactsSchema( filteredArtifactSchema )
26
+ filteredArtifactSchema = flattenedArtifactsSchema.find(
27
+ artifact => artifact.name === artifactName )
28
+ } else if ( process.argv.length === 5 ) {
29
+ artifactsYmlPath = process.argv[2]
30
+ artifactName = process.argv[3]
31
+ artifactPackageName = process.argv[4]
32
+ artifactPackageVersion = process.argv[5]
33
+ filteredArtifactSchema = await getArtifactsSchema( artifactsYmlPath )
34
+ const flattenedArtifactsSchema = flattenArtifactsSchema( filteredArtifactSchema )
35
+ filteredArtifactSchema = flattenedArtifactsSchema.filter(
36
+ artifact => artifact.gcp_artifact_registry_package_name === artifactPackageName &&
37
+ artifact.gcp_artifact_registry_package_version === artifactPackageVersion )
38
+ } else {
39
+ console.error( 'Usage:' )
40
+ console.error( ' pull-artifact.mjs <artifacts.yml>' )
41
+ console.error( ' pull-artifact.mjs <artifacts.yml> <artifact name>' )
42
+ console.error( ' pull-artifact.mjs <artifacts.yml> <artifact package name> <artifact package version>' )
43
+ process.exit( 1 )
44
+ }
45
+
46
+ // TODO: Use concurrency to pull artifacts and provide summary of results.
47
+ for ( const artifactSchema of filteredArtifactSchema ) {
48
+ let puller
49
+ switch ( artifactSchema.type ) {
50
+ case ArtifactTypeEnum.GENERIC:
51
+ puller = new GenericArtifactPuller( artifactSchema )
52
+ break
53
+ default:
54
+ warning( `Unsupported artifact type "${artifactSchema.type}"` )
55
+ continue
56
+ }
57
+
58
+ if ( !puller ) {
59
+ warning( `Unsupported artifact type "${artifactSchema.type}"` )
60
+ continue
61
+ }
62
+
63
+ // eslint-disable-next-line no-await-in-loop
64
+ await puller.pull()
65
+ }
5
66
  }
6
67
 
7
68
  main()
@@ -8,46 +8,60 @@ import { GenericArtifactPusher } from './ArtifactPusher.mjs'
8
8
 
9
9
  async function main() {
10
10
 
11
- // If an argument is provided, use it as the artifacts.yml file path
12
- const artifactsYmlPath = process.argv[2]
13
- const artifactPackageName = process.argv[3]
14
- const artifactPackageVersion = process.argv[4]
15
-
16
- if ( artifactsYmlPath ) {
17
- const artifactsSchema = await getArtifactsSchema( artifactsYmlPath )
18
- const flattenedArtifactsSchema = flattenArtifactsSchema( artifactsSchema )
19
-
20
- // Open for unexpected matches if we end up re-using the same package name and version for
21
- // multiple artifacts spread across multiple repositories and/or projects.
22
- const filteredArtifactSchemas = flattenedArtifactsSchema.filter(
11
+ let artifactsYmlPath = null
12
+ let artifactName = null
13
+ let artifactPackageName = null
14
+ let artifactPackageVersion = null
15
+ let filteredArtifactSchema = null
16
+
17
+ if ( process.argv.length === 3 ) {
18
+ artifactsYmlPath = process.argv[2]
19
+ filteredArtifactSchema = await getArtifactsSchema( artifactsYmlPath )
20
+ const flattenedArtifactsSchema = flattenArtifactsSchema( filteredArtifactSchema )
21
+ filteredArtifactSchema = flattenedArtifactsSchema
22
+ } else if ( process.argv.length === 4 ) {
23
+ artifactsYmlPath = process.argv[2]
24
+ filteredArtifactSchema = await getArtifactsSchema( artifactsYmlPath )
25
+ const flattenedArtifactsSchema = flattenArtifactsSchema( filteredArtifactSchema )
26
+ filteredArtifactSchema = flattenedArtifactsSchema.find(
27
+ artifact => artifact.name === artifactName )
28
+ } else if ( process.argv.length === 5 ) {
29
+ artifactsYmlPath = process.argv[2]
30
+ artifactName = process.argv[3]
31
+ artifactPackageName = process.argv[4]
32
+ artifactPackageVersion = process.argv[5]
33
+ filteredArtifactSchema = await getArtifactsSchema( artifactsYmlPath )
34
+ const flattenedArtifactsSchema = flattenArtifactsSchema( filteredArtifactSchema )
35
+ filteredArtifactSchema = flattenedArtifactsSchema.filter(
23
36
  artifact => artifact.gcp_artifact_registry_package_name === artifactPackageName &&
24
37
  artifact.gcp_artifact_registry_package_version === artifactPackageVersion )
25
-
26
- if ( filteredArtifactSchemas.length === 0 ) {
27
- console.error( `No artifacts found for ${artifactPackageName} version ${artifactPackageVersion} in ${artifactsYmlPath}` )
28
- process.exit( 1 )
29
- }
38
+ } else {
39
+ console.error( 'Usage:' )
40
+ console.error( ' push-artifact.mjs <artifacts.yml>' )
41
+ console.error( ' push-artifact.mjs <artifacts.yml> <artifact name>' )
42
+ console.error( ' push-artifact.mjs <artifacts.yml> <artifact package name> <artifact package version>' )
43
+ process.exit( 1 )
44
+ }
30
45
 
31
- // TODO: Use concurrency to package artifacts and provide summary of results.
32
- for ( const artifactSchema of filteredArtifactSchemas ) {
33
- let packager
34
- switch ( artifactSchema.type ) {
35
- case ArtifactTypeEnum.GENERIC:
36
- packager = new GenericArtifactPusher( artifactSchema )
37
- break
38
- default:
39
- warning( `Unsupported artifact type "${artifactSchema.type}"` )
40
- continue
41
- }
42
-
43
- if ( !packager ) {
46
+ // TODO: Use concurrency to push artifacts and provide summary of results.
47
+ for ( const artifactSchema of filteredArtifactSchema ) {
48
+ let pusher
49
+ switch ( artifactSchema.type ) {
50
+ case ArtifactTypeEnum.GENERIC:
51
+ pusher = new GenericArtifactPusher( artifactSchema )
52
+ break
53
+ default:
44
54
  warning( `Unsupported artifact type "${artifactSchema.type}"` )
45
55
  continue
46
- }
56
+ }
47
57
 
48
- // eslint-disable-next-line no-await-in-loop
49
- await packager.package()
58
+ if ( !pusher ) {
59
+ warning( `Unsupported artifact type "${artifactSchema.type}"` )
60
+ continue
50
61
  }
62
+
63
+ // eslint-disable-next-line no-await-in-loop
64
+ await pusher.push()
51
65
  }
52
66
  }
53
67