@leverege/build-tools 2.92.0 → 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.
@@ -0,0 +1,3 @@
1
+ {
2
+ "editor.formatOnSave": true
3
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.92.0",
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": {
@@ -11,7 +11,7 @@
11
11
  "clean": "rm -rf lib",
12
12
  "lint": "find ./src -name \\*.\\*js | xargs npx eslint --report-unused-disable-directives",
13
13
  "prepare": "[ $SKIP_PREPARE ] && exit 0 || ./src/hook-and-release.mjs",
14
- "test": "echo \"no tests specified\" && exit 0",
14
+ "test": "mocha -t 60000 --exit 'test/**/*.mjs'",
15
15
  "prepack": "npm exec prepack"
16
16
  },
17
17
  "bin": {
@@ -54,7 +54,9 @@
54
54
  "pkglint": "src/pkglint.sh",
55
55
  "prepack": "src/prepack.mjs",
56
56
  "prune-git": "src/prune-git.sh",
57
+ "pull-artifact": "src/artifacts/pull-artifact.mjs",
57
58
  "pull-git": "src/pull-git.sh",
59
+ "push-artifact": "src/artifacts/push-artifact.mjs",
58
60
  "push-my-chart": "src/push-my-chart.mjs",
59
61
  "refresh-npm-token": "src/refresh-npm-token.mjs",
60
62
  "refresh-py-idx": "src/refresh-py-idx.sh",
@@ -91,11 +93,14 @@
91
93
  "shell-quote": "^1.8.3",
92
94
  "simple-git": "^3.30.0",
93
95
  "sloc": "^0.3.2",
96
+ "superstruct": "^2.0.2",
94
97
  "toml": "^3.0.0",
95
98
  "zx": "^8.8.5"
96
99
  },
97
100
  "devDependencies": {
98
101
  "@leverege/eslint-config-leverege": "^5.1.1",
102
+ "chai": "^6.2.1",
103
+ "mocha": "^11.7.5",
99
104
  "npm": "^11.6.2"
100
105
  }
101
- }
106
+ }
package/src/Utils.mjs CHANGED
@@ -224,6 +224,15 @@ export const gitRepoIsDirty = async () => {
224
224
  return cleanliness?.length > 0
225
225
  }
226
226
 
227
+ export const parseYamlFile = async ( filePath ) => {
228
+ try {
229
+ const fileContent = await fs.promises.readFile( filePath, 'utf8' )
230
+ return YAML.load( fileContent )
231
+ } catch ( error ) {
232
+ throw new Error( `Failed to parse YAML file ${filePath}: ${error.message}` )
233
+ }
234
+ }
235
+
227
236
  export const parseJsonFile = async ( jsonFile ) => {
228
237
  // TODO: rework this file exists logic / throw
229
238
  if ( !fs.existsSync( jsonFile ) ) { return undefined } // eslint-disable-line security/detect-non-literal-fs-filename
@@ -0,0 +1,148 @@
1
+ import fs from 'fs'
2
+
3
+ import { toExplicitPath } from './Utils.mjs'
4
+
5
+ class ArtifactPuller {
6
+ constructor( artifact ) {
7
+ this.artifact = artifact
8
+ }
9
+
10
+ async pull() {
11
+ throw new Error( 'Not implemented' )
12
+ }
13
+ }
14
+
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
+ }
118
+
119
+ async pull() {
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
145
+ }
146
+ }
147
+
148
+ export { ArtifactPuller, GenericArtifactPuller }
@@ -0,0 +1,78 @@
1
+ class ArtifactPusher {
2
+ constructor( artifact ) {
3
+ this.artifact = artifact
4
+ }
5
+
6
+ async push() {
7
+ throw new Error( 'Not implemented' )
8
+ }
9
+ }
10
+
11
+ class GenericArtifactPusher extends ArtifactPusher {
12
+
13
+ async listFiles( ) {
14
+ const command = `gcloud artifacts files list \
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"`
21
+
22
+ console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
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 )
29
+
30
+ return files
31
+ }
32
+
33
+ async push() {
34
+ console.log( 'Pushing artifact to registry...' )
35
+
36
+ if ( this.artifact.remote_file_path ) {
37
+ return false
38
+ }
39
+
40
+ console.log( 'Uploading artifact to registry...' )
41
+
42
+ let command = ''
43
+
44
+ command = `gcloud artifacts generic upload \
45
+ --project=${this.artifact.gcp_project_id} \
46
+ --location=${this.artifact.gcp_location} \
47
+ --repository=${this.artifact.gcp_artifact_registry_repository_name} \
48
+ --package=${this.artifact.gcp_artifact_registry_package_name} \
49
+ --version=${this.artifact.gcp_artifact_registry_package_version}`
50
+
51
+ if ( this.artifact.local_path ) {
52
+ command += ` --source-directory=${this.artifact.local_path}`
53
+ command += ' --skip-existing'
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}`
60
+ }
61
+
62
+ command += ` --destination-path=${this.artifact.remote_path}`
63
+
64
+ console.log( 'Command:', command.replace( /\s+/g, ' ' ).trim() )
65
+
66
+ try {
67
+ const { execSync } = await import( 'child_process' )
68
+ execSync( command, { encoding : 'utf8', stdio : 'pipe' } )
69
+ console.log( `Successfully published artifact: ${this.artifact.gcp_artifact_registry_package_name}:${this.artifact.gcp_artifact_registry_package_version}` )
70
+ return true
71
+ } catch ( error ) {
72
+ console.error( 'Error publishing artifact:', error.message )
73
+ return false
74
+ }
75
+ }
76
+ }
77
+
78
+ export { ArtifactPusher, GenericArtifactPusher }
@@ -0,0 +1,91 @@
1
+ import { assign, object, string, array, optional, enums, union, refine } from 'superstruct'
2
+
3
+ const ArtifactTypeEnum = {
4
+ GENERIC : 'generic',
5
+ }
6
+
7
+ // Superstruct schema for individual artifact configuration
8
+ const PartialArtifactSchema = object( {
9
+ name : string(),
10
+ type : optional( enums( Object.values( ArtifactTypeEnum ) ) ),
11
+ gcp_project_id : optional( string() ),
12
+ gcp_location : optional( string() ),
13
+ gcp_artifact_registry_repository_name : optional( string() ),
14
+ gcp_artifact_registry_package_name : optional( string() ),
15
+ gcp_artifact_registry_package_version : optional( string() )
16
+ } )
17
+
18
+ const ArtifactSchema = assign( PartialArtifactSchema, object( {
19
+ name : string(),
20
+ type : enums( Object.values( ArtifactTypeEnum ) ),
21
+ gcp_project_id : string(),
22
+ gcp_location : string(),
23
+ gcp_artifact_registry_repository_name : string(),
24
+ gcp_artifact_registry_package_name : string(),
25
+ gcp_artifact_registry_package_version : string()
26
+ } ) )
27
+
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
+ )
47
+
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
+ )
66
+
67
+ // Superstruct schema for defaults configuration
68
+ const DefaultsSchema = object( {
69
+ gcp_project_id : optional( string() ),
70
+ gcp_location : optional( string() ),
71
+ gcp_artifact_registry_repository_name : optional( string() ),
72
+ gcp_artifact_registry_package_name : optional( string() ),
73
+ gcp_artifact_registry_package_version : optional( string() )
74
+ } )
75
+
76
+ // Superstruct schema for the complete artifacts configuration with defaults
77
+ const ArtifactsSchema = object( {
78
+ defaults : optional( DefaultsSchema ),
79
+ artifacts : array( union( [ PartialArtifactSchema, PartialGenericArtifactSchema ] ) )
80
+ } )
81
+
82
+ const FlattenedArtifactsSchema = array( assign( union( [ ArtifactSchema, GenericArtifactSchema ] ) ) )
83
+
84
+ export {
85
+ ArtifactTypeEnum,
86
+ ArtifactsSchema,
87
+ FlattenedArtifactsSchema,
88
+ ArtifactSchema,
89
+ DefaultsSchema,
90
+ GenericArtifactSchema,
91
+ }
@@ -0,0 +1,113 @@
1
+ import fs from 'fs'
2
+ import crypto from 'crypto'
3
+
4
+ import { validate } from 'superstruct'
5
+
6
+ import { parseYamlFile, warning } from '../Utils.mjs'
7
+
8
+ import { ArtifactTypeEnum, ArtifactsSchema, GenericArtifactSchema } from './Structs.mjs'
9
+
10
+ const getArtifactsSchema = async ( artifactsFilePath = './artifacts.yml' ) => {
11
+ const artifactsConfig = await parseYamlFile( artifactsFilePath )
12
+ const [ error, result ] = validate( artifactsConfig, ArtifactsSchema )
13
+ if ( error ) {
14
+ throw new Error( `Invalid artifacts.yml file: ${error.message}` )
15
+ }
16
+ return result
17
+ }
18
+
19
+ const flattenArtifactsSchema = ( artifactsSchema ) => {
20
+ return artifactsSchema.artifacts.reduce( ( flattenedArtifacts, artifact ) => {
21
+ const mergedArtifact = {
22
+ ...artifactsSchema.defaults,
23
+ ...artifact
24
+ }
25
+
26
+ let schema
27
+ switch ( mergedArtifact.type ) {
28
+ case ArtifactTypeEnum.GENERIC:
29
+ schema = GenericArtifactSchema
30
+ break
31
+ default:
32
+ warning( `Unsupported artifact type "${mergedArtifact.type}"` )
33
+ break
34
+ }
35
+
36
+ if ( !schema ) {
37
+ warning( `Invalid artifact type "${mergedArtifact.type}"` )
38
+ return flattenedArtifacts
39
+ }
40
+
41
+ const [ error, validatedArtifact ] = validate( mergedArtifact, schema )
42
+
43
+ if ( error ) {
44
+ warning( `Invalid artifact "${mergedArtifact.name}": ${error.message}` )
45
+ return flattenedArtifacts
46
+ }
47
+
48
+ return [ ...flattenedArtifacts, validatedArtifact ]
49
+ }, [] )
50
+ }
51
+
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 }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
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
+
9
+ async function main() {
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
+ }
66
+ }
67
+
68
+ main()
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { warning } from '../Utils.mjs'
4
+
5
+ import { getArtifactsSchema, flattenArtifactsSchema } from './Utils.mjs'
6
+ import { ArtifactTypeEnum } from './Structs.mjs'
7
+ import { GenericArtifactPusher } from './ArtifactPusher.mjs'
8
+
9
+ async function main() {
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( ' 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
+ }
45
+
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:
54
+ warning( `Unsupported artifact type "${artifactSchema.type}"` )
55
+ continue
56
+ }
57
+
58
+ if ( !pusher ) {
59
+ warning( `Unsupported artifact type "${artifactSchema.type}"` )
60
+ continue
61
+ }
62
+
63
+ // eslint-disable-next-line no-await-in-loop
64
+ await pusher.push()
65
+ }
66
+ }
67
+
68
+ main()
Binary file