@leverege/build-tools 2.113.6 → 2.114.0-DEVOP-578.2

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.
Files changed (41) hide show
  1. package/README.md +0 -15
  2. package/package.json +15 -10
  3. package/src/bash-funcs +1 -1
  4. package/src/build-tools.mjs +3 -2
  5. package/src/chart-compass.yaml +6 -1
  6. package/src/helm-charts/api-server/values-local.yaml +1 -1
  7. package/src/helm-charts/cnpg-db-psql-stack/cluster.yaml.ovh +1 -1
  8. package/src/helm-charts/cnpg-db-tsdb-basic/cluster.yaml.ovh +1 -1
  9. package/src/helm-charts/cnpg-db-tsdb-dense/cluster.yaml.ovh +1 -1
  10. package/src/helm-charts/llm-prompt-server/values-local.yaml +5 -0
  11. package/src/helm-charts/prom-operator/helmup.plugin +3 -3
  12. package/src/helm-charts/prom-operator/prometheus-stack.yaml.ovh +1 -1
  13. package/src/helm-charts/triton-inference-server/values-local.yaml +28 -0
  14. package/src/helm-charts/vms-server/values-local.yaml +45 -0
  15. package/src/helmup.sh +5 -4
  16. package/src/k8s/commands/completion.mjs +100 -0
  17. package/src/k8s/commands/cryo.mjs +164 -0
  18. package/src/k8s/commands/exe.mjs +57 -0
  19. package/src/k8s/commands/fwd.mjs +35 -0
  20. package/src/k8s/commands/log.mjs +76 -0
  21. package/src/k8s/commands/roll.mjs +37 -0
  22. package/src/k8s/commands/scale.mjs +43 -0
  23. package/src/k8s/k8s.mjs +26 -0
  24. package/src/k8s/lib/gate.mjs +9 -0
  25. package/src/k8s/lib/kubectl.mjs +26 -0
  26. package/src/k8s/lib/select.mjs +18 -0
  27. package/src/overwhelm.mjs +1 -1
  28. package/src/repo-panopticon.mjs +16 -12
  29. package/src/service-man/config/Config.mjs +1 -1
  30. package/src/service-man/config/iam-roles/leveregeVertexEndpointUser.json +10 -0
  31. package/src/service-man/config/service-accounts/llm-prompt-server.json +6 -0
  32. package/src/service-man/config/service-accounts/triton-inference-server.json +5 -0
  33. package/src/service-man/config/service-accounts/vms-server.json +8 -0
  34. package/src/service-man/gcloud-k8s/ServiceAccountManager.mjs +9 -5
  35. package/src/artifacts/ArtifactPuller.mjs +0 -131
  36. package/src/artifacts/ArtifactPusher.mjs +0 -110
  37. package/src/artifacts/Structs.mjs +0 -98
  38. package/src/artifacts/Utils.mjs +0 -284
  39. package/src/artifacts/pull-artifact.mjs +0 -81
  40. package/src/artifacts/push-artifact.mjs +0 -80
  41. package/src/change-up.sh +0 -27
@@ -1,110 +0,0 @@
1
- import path from 'node:path'
2
- import fs from 'node:fs'
3
-
4
- import { shellCmd, log, err, debug } from '../Utils.mjs'
5
-
6
- import {
7
- parseGenericArtifactFileToRemoteRelativePath,
8
- parseGenericArtifactSchemaToRemoteRelativePath,
9
- listGenericArtifactFiles,
10
- shouldUseIgnoreConfiguration,
11
- findIgnoreFilePath,
12
- copyFilesWithIgnoreConfiguration
13
- } from './Utils.mjs'
14
-
15
- class ArtifactPusher {
16
- constructor( path, artifact ) {
17
- this.path = path
18
- this.artifact = artifact
19
- }
20
-
21
- async push() {
22
- throw new Error( 'Not implemented' )
23
- }
24
- }
25
-
26
- class GenericArtifactPusher extends ArtifactPusher {
27
-
28
- async push() {
29
- log( `Pushing artifact: ${this.artifact.name}` )
30
-
31
- if ( this.artifact.remote_file_path ) {
32
- err( 'Remote file path is not supported for pushing artifacts' )
33
- return false
34
- }
35
-
36
- if ( !this.artifact.local_path && !this.artifact.local_file_path ) {
37
- err( 'Local path or local file path is required for pushing artifacts' )
38
- return false
39
- }
40
-
41
- try {
42
- let command = ''
43
-
44
- command = `gcloud artifacts generic upload \
45
- --project=${this.artifact.project} \
46
- --location=${this.artifact.location} \
47
- --repository=${this.artifact.repository} \
48
- --package=${this.artifact.package} \
49
- --version=${this.artifact.version}`
50
-
51
- let pathToDelete
52
-
53
- if ( this.artifact.local_path ) {
54
- const originalLocalPath = path.join( this.path, this.artifact.local_path )
55
-
56
- let localPath = originalLocalPath
57
-
58
- const useIgnoreConfiguration = await shouldUseIgnoreConfiguration()
59
-
60
- if ( useIgnoreConfiguration ) {
61
- const ignoreFilePath = await findIgnoreFilePath( this.path )
62
- if ( ignoreFilePath ) {
63
- const tmpLocalPath = path.join( '/', 'tmp', `${this.artifact.project}_${this.artifact.location}_${this.artifact.repository}_${this.artifact.package}_${this.artifact.version}` )
64
- localPath = tmpLocalPath
65
- pathToDelete = tmpLocalPath
66
- await copyFilesWithIgnoreConfiguration( originalLocalPath, tmpLocalPath, ignoreFilePath )
67
- }
68
- }
69
-
70
- command += ` --source-directory=${localPath}`
71
- command += ' --skip-existing'
72
- } else if ( this.artifact.local_file_path ) {
73
-
74
- const files = await listGenericArtifactFiles( this.artifact )
75
-
76
- const newRemoteFilePath = parseGenericArtifactSchemaToRemoteRelativePath( this.artifact )
77
-
78
- for ( const file of files ) {
79
- const existingRemoteFilePath = parseGenericArtifactFileToRemoteRelativePath( file )
80
- if ( existingRemoteFilePath === newRemoteFilePath ) {
81
- err( `File already exists in the artifact registry: ${existingRemoteFilePath}` )
82
- return false
83
- }
84
- }
85
- const localPath = path.join( this.path, this.artifact.local_file_path )
86
- command += ` --source=${localPath}`
87
- }
88
-
89
- command += ` --destination-path=${this.artifact.remote_path || '""'}`
90
-
91
- debug( { command }, '<==Upload Command' )
92
-
93
- await shellCmd( command )
94
-
95
- if ( pathToDelete ) {
96
- await fs.promises.rm( pathToDelete, { recursive : true } )
97
- }
98
-
99
- log( `Successfully pushed artifact: ${this.artifact.name}` )
100
-
101
- return true
102
- } catch ( error ) {
103
- debug( { error }, '<==Error Pushing Artifact' )
104
- err( `Error pushing artifact: ${this.artifact.name} ${error.message}` )
105
- return false
106
- }
107
- }
108
- }
109
-
110
- export { ArtifactPusher, GenericArtifactPusher }
@@ -1,98 +0,0 @@
1
- import path from 'node:path'
2
-
3
- import { assign, coerce, object, string, array, optional, enums, union, refine } from 'superstruct'
4
-
5
- const ArtifactTypeEnum = {
6
- GENERIC : 'generic',
7
- }
8
-
9
- // Structs with the Partial prefix come from the need to validate the schema with defaults and without defaults merged together.
10
-
11
- const PartialArtifactSchema = object( {
12
- name : string(),
13
- type : optional( enums( Object.values( ArtifactTypeEnum ) ) ),
14
- project : optional( string() ),
15
- location : optional( string() ),
16
- repository : optional( string() ),
17
- package : optional( string() ),
18
- version : optional( string() )
19
- } )
20
-
21
- const ArtifactSchema = assign( PartialArtifactSchema, object( {
22
- name : string(),
23
- type : enums( Object.values( ArtifactTypeEnum ) ),
24
- project : string(),
25
- location : string(),
26
- repository : string(),
27
- package : string(),
28
- version : string()
29
- } ) )
30
-
31
- const normalizedPath = () => coerce( string(), string(), value => path.normalize( value ) )
32
-
33
- const PartialGenericArtifactSchema = refine(
34
- assign( PartialArtifactSchema, object( {
35
- type : optional( enums( [ ArtifactTypeEnum.GENERIC ] ) ),
36
- local_file_path : optional( normalizedPath() ),
37
- local_path : optional( normalizedPath() ),
38
- remote_file_path : optional( normalizedPath() ),
39
- remote_path : optional( normalizedPath() )
40
- } ) ),
41
- 'ConflictingPaths',
42
- ( value ) => {
43
- if ( value.local_file_path && value.local_path ) {
44
- return 'Only one of local_file_path or local_path must be provided'
45
- }
46
- if ( value.remote_file_path && value.remote_path ) {
47
- return 'Only one of remote_file_path or remote_path must be provided'
48
- }
49
- return true
50
- }
51
- )
52
-
53
- const GenericArtifactSchema = refine(
54
- assign( ArtifactSchema, object( {
55
- type : enums( [ ArtifactTypeEnum.GENERIC ] ),
56
- local_file_path : optional( normalizedPath() ),
57
- local_path : optional( normalizedPath() ),
58
- remote_file_path : optional( string() ),
59
- remote_path : optional( normalizedPath() )
60
- } ) ),
61
- 'ConflictingPaths',
62
- ( value ) => {
63
- if ( value.local_file_path && value.local_path ) {
64
- return 'Only one of local_file_path or local_path must be provided'
65
- }
66
- if ( value.remote_file_path && value.remote_path ) {
67
- return 'Only one of remote_file_path or remote_path must be provided'
68
- }
69
- return true
70
- }
71
- )
72
-
73
- // Superstruct schema for defaults configuration
74
- const DefaultsSchema = object( {
75
- type : optional( enums( Object.values( ArtifactTypeEnum ) ) ),
76
- project : optional( string() ),
77
- location : optional( string() ),
78
- repository : optional( string() ),
79
- package : optional( string() ),
80
- version : optional( string() )
81
- } )
82
-
83
- // Superstruct schema for the complete artifacts configuration with defaults
84
- const ArtifactsSchema = object( {
85
- defaults : optional( DefaultsSchema ),
86
- artifacts : array( union( [ PartialArtifactSchema, PartialGenericArtifactSchema ] ) )
87
- } )
88
-
89
- const FlattenedArtifactsSchema = array( assign( union( [ ArtifactSchema, GenericArtifactSchema ] ) ) )
90
-
91
- export {
92
- ArtifactTypeEnum,
93
- ArtifactsSchema,
94
- FlattenedArtifactsSchema,
95
- ArtifactSchema,
96
- DefaultsSchema,
97
- GenericArtifactSchema,
98
- }
@@ -1,284 +0,0 @@
1
- import fs from 'node:fs'
2
- import path from 'node:path'
3
- import crypto from 'node:crypto'
4
-
5
- import { validate } from 'superstruct'
6
-
7
- import { parseYamlFile, err, warning, debug, shellCmd } from '../Utils.mjs'
8
-
9
- import { ArtifactTypeEnum, ArtifactsSchema, GenericArtifactSchema } from './Structs.mjs'
10
-
11
- const getArtifactsSchema = async ( artifactsFilePath = './artifacts.yaml' ) => {
12
- const artifactsConfig = await parseYamlFile( artifactsFilePath )
13
- const [ error, result ] = validate( artifactsConfig, ArtifactsSchema )
14
- if ( error ) {
15
- err( `Invalid artifacts.yml file: ${error.message}` )
16
- debug( { err : error }, '<==Invalid artifacts.yml file' )
17
- throw new Error( `Invalid artifacts.yml file: ${error.message}` )
18
- }
19
- return result
20
- }
21
-
22
- const flattenArtifactsSchema = ( artifactsSchema ) => {
23
- return artifactsSchema.artifacts.reduce( ( flattenedArtifacts, artifact ) => {
24
- const mergedArtifact = {
25
- ...artifactsSchema.defaults,
26
- ...artifact
27
- }
28
-
29
- let schema
30
- switch ( mergedArtifact.type ) {
31
- case ArtifactTypeEnum.GENERIC:
32
- schema = GenericArtifactSchema
33
- break
34
- default:
35
- warning( `Unsupported artifact type "${mergedArtifact.type}"` )
36
- break
37
- }
38
-
39
- if ( !schema ) {
40
- warning( `Invalid artifact type "${mergedArtifact.type}"` )
41
- return flattenedArtifacts
42
- }
43
-
44
- const [ error, validatedArtifact ] = validate( mergedArtifact, schema )
45
-
46
- if ( error ) {
47
- warning( `Invalid artifact "${mergedArtifact.name}": ${error.message}` )
48
- return flattenedArtifacts
49
- }
50
-
51
- return [ ...flattenedArtifacts, validatedArtifact ]
52
- }, [] )
53
- }
54
-
55
- // Example of a file in a generic artifact registry repository:
56
- // [
57
- // {
58
- // "createTime": "2025-12-02T17:52:08.694541Z",
59
- // "hashes": [
60
- // {
61
- // "type": "SHA256",
62
- // "value": "wrBRqJOUjm-zy6B7YzgKlK0fv9Ad0EEjydBnsmc9Ruw="
63
- // },
64
- // {
65
- // "type": "MD5",
66
- // "value": "Ebp3fVphzrITJ461Mg7Kmg=="
67
- // }
68
- // ],
69
- // "name": "projects/leverege-registry/locations/us-central1/repositories/test-generic-registry/files/sweet-poems-1-1764697925426:v1:test1.txt%2Ftest1.txt",
70
- // "owner": "projects/leverege-registry/locations/us-central1/repositories/test-generic-registry/packages/sweet-poems-1-1764697925426/versions/v1",
71
- // "sizeBytes": "40",
72
- // "updateTime": "2025-12-02T17:52:08.694541Z"
73
- // }
74
- // ]
75
- // Obtained with:gcloud artifacts files list --project=leverege-registry --location=us-central1 --repository=test-generic-registry --package=sweet-poems-1-1764697925426 --version v1 --format="json"
76
-
77
- const parseGenericArtifactFileToRemoteRelativePath = ( genericArtifactFile ) => {
78
- // "projects/leverege-registry/locations/us-central1/repositories/test-generic-registry/files/sweet-poems-1-1764697925426:v1:test1.txt%2Ftest1.txt"
79
- const artifactFileName = genericArtifactFile.name.split( '/' ).pop()
80
- // sweet-poems-1-1764697925426:v1:test1.txt%2Ftest1.txt
81
- const remoteRelativePath = artifactFileName.split( ':' ).pop().replaceAll( '%2F', '/' )
82
- // test1.txt
83
- return path.normalize( remoteRelativePath )
84
- }
85
-
86
- const parseGenericArtifactSchemaToRemoteRelativePath = ( genericArtifactSchema ) => {
87
- if ( genericArtifactSchema.remote_file_path ) {
88
- return path.normalize( genericArtifactSchema.remote_file_path )
89
- }
90
- if ( genericArtifactSchema.remote_path && genericArtifactSchema.local_file_path ) {
91
- return path.join( genericArtifactSchema.remote_path, path.basename( genericArtifactSchema.local_file_path ) )
92
- }
93
- if ( !genericArtifactSchema.remote_file_path && !genericArtifactSchema.remote_path && genericArtifactSchema.local_file_path ) {
94
- return path.basename( genericArtifactSchema.local_file_path )
95
- }
96
- if ( !genericArtifactSchema.remote_file_path && !genericArtifactSchema.remote_path && genericArtifactSchema.local_file_path ) {
97
- return path.basename( genericArtifactSchema.local_file_path )
98
- }
99
- if ( genericArtifactSchema.remote_path && genericArtifactSchema.local_path ) {
100
- return path.normalize( genericArtifactSchema.remote_path )
101
- }
102
- return path.normalize( '.' )
103
- }
104
-
105
- const parseGenericArtifactSchemaToLocalRelativePath = ( genericArtifactSchema ) => {
106
- if ( genericArtifactSchema.local_file_path ) {
107
- return path.normalize( genericArtifactSchema.local_file_path )
108
- }
109
- if ( genericArtifactSchema.local_path && genericArtifactSchema.remote_file_path ) {
110
- return path.join( genericArtifactSchema.local_path, path.basename( genericArtifactSchema.remote_file_path ) )
111
- }
112
- if ( genericArtifactSchema.local_path && !genericArtifactSchema.remote_file_path && !genericArtifactSchema.remote_file_path ) {
113
- return path.normalize( genericArtifactSchema.local_path )
114
- }
115
- if ( !genericArtifactSchema.local_file_path && !genericArtifactSchema.local_path && genericArtifactSchema.remote_file_path ) {
116
- return path.basename( genericArtifactSchema.remote_file_path )
117
- }
118
- return path.normalize( '.' )
119
- }
120
-
121
- const parseGenericArtifactSchemaToArtifactNameBase = ( genericArtifactSchema ) => {
122
- const elements = [
123
- 'projecs',
124
- genericArtifactSchema.project,
125
- 'locations',
126
- genericArtifactSchema.location,
127
- 'repositories',
128
- genericArtifactSchema.repository,
129
- 'files',
130
- ]
131
- return elements.join( '/' )
132
- }
133
-
134
- const parseGenericArtifactSchemaToArtifactNameFile = ( genericArtifactSchema ) => {
135
- // // "name": "projects/leverege-registry/locations/us-central1/repositories/test-generic-registry/files/sweet-poems-1-1764697925426:v1:test1.txt%2Ftest1.txt",
136
-
137
- const remoteRelativePath = parseGenericArtifactSchemaToRemoteRelativePath( genericArtifactSchema )
138
- const encodedRemoteRelativePath = encodeURIComponent( remoteRelativePath )
139
-
140
- const elements = [
141
- genericArtifactSchema.package,
142
- genericArtifactSchema.version,
143
- encodedRemoteRelativePath,
144
- ]
145
- return elements.join( ':' )
146
- }
147
-
148
- const parseGenericArtifactSchemaToArtifactName = ( genericArtifactSchema ) => {
149
- const base = parseGenericArtifactSchemaToArtifactNameBase( genericArtifactSchema )
150
- const file = parseGenericArtifactSchemaToArtifactNameFile( genericArtifactSchema )
151
-
152
- const elements = [
153
- base,
154
- file,
155
- ]
156
-
157
- return elements.join( ':' )
158
- }
159
-
160
- const calculateHash = async ( path ) => {
161
- try {
162
- const hash = crypto.createHash( 'sha256' )
163
- hash.update( await fs.promises.readFile( path ) ) // eslint-disable-line security/detect-non-literal-fs-filename
164
- return `${hash.digest( 'base64url' )}=`
165
- } catch ( error ) {
166
- throw new Error( `Failed to calculate hash for artifact ${path}: ${error.message}` )
167
- }
168
- }
169
-
170
- const listGenericArtifactFiles = async ( artifact ) => {
171
- const command = `gcloud artifacts files list \
172
- --project=${artifact.project} \
173
- --location=${artifact.location} \
174
- --repository=${artifact.repository} \
175
- --package=${artifact.package} \
176
- --version ${artifact.version} \
177
- --format="json"`
178
-
179
- debug( { command }, '<==List Files Command' )
180
-
181
- const result = await shellCmd( command )
182
-
183
- // Parse the JSON response
184
- const files = JSON.parse( result )
185
- return files
186
- }
187
-
188
- const getMissingRemoteFiles = async ( genericArtifactFiles, genericArtifactSchemaPath, genericArtifactSchema ) => {
189
-
190
- const expectedRemoteRelativePath = parseGenericArtifactSchemaToRemoteRelativePath( genericArtifactSchema )
191
- const localRelativePath = parseGenericArtifactSchemaToLocalRelativePath( genericArtifactSchema )
192
- const expectedLocalRelativePath = path.join( genericArtifactSchemaPath, localRelativePath )
193
-
194
- const actualFiles = new Set()
195
- const expectedFiles = new Set()
196
-
197
- for ( const file of genericArtifactFiles ) {
198
- const actualRemoteFilePath = parseGenericArtifactFileToRemoteRelativePath( file )
199
- const actualRemoteFileHash = file.hashes.find( hash => hash.type === 'SHA256' ).value
200
- actualFiles.add( { remoteFilePath : actualRemoteFilePath, remoteFileHash : actualRemoteFileHash } )
201
- }
202
-
203
- /* eslint-disable security/detect-non-literal-fs-filename */
204
- if ( ( await fs.promises.stat( expectedLocalRelativePath ) ).isDirectory() ) {
205
- const localFiles = await fs.promises.readdir( expectedLocalRelativePath, { withFileTypes : true, recursive : true } )
206
- for ( const localFile of localFiles ) {
207
- if ( localFile.isDirectory() ) {
208
- continue
209
- }
210
-
211
- const expectedRemoteFilePath = path.join( expectedRemoteRelativePath, localFile.path.replace( expectedLocalRelativePath, '' ), localFile.name )
212
- const expectedLocalFilePath = path.join( localFile.path, localFile.name )
213
- // eslint-disable-next-line no-await-in-loop
214
- expectedFiles.add( { remoteFilePath : expectedRemoteFilePath, remoteFileHash : await calculateHash( expectedLocalFilePath ) } )
215
- }
216
- } else {
217
- const expectedRemoteFilePath = expectedRemoteRelativePath
218
- const expectedLocalFilePath = expectedLocalRelativePath
219
- expectedFiles.add( { remoteFilePath : expectedRemoteFilePath, remoteFileHash : await calculateHash( expectedLocalFilePath ) } )
220
- }
221
- /* eslint-enable security/detect-non-literal-fs-filename */
222
-
223
- const actualArray = Array.from( actualFiles )
224
- const expectedArray = Array.from( expectedFiles )
225
-
226
- return expectedArray.filter( expected => !actualArray.some( actual => actual.remoteFilePath === expected.remoteFilePath && actual.remoteFileHash === expected.remoteFileHash ) )
227
- }
228
-
229
- const shouldUseIgnoreConfiguration = async () => {
230
- let result
231
- try {
232
- result = await shellCmd( 'gcloud config get-value gcloudignore/enabled' )
233
- if ( result.trim() === '' || result.includes( 'has no property' ) ) {
234
- return false
235
- }
236
- return result.trim() === 'true'
237
- } catch ( error ) {
238
- if ( error.message && error.message.includes( 'Section [gcloudignore] has no property [enabled]' ) ) {
239
- return false
240
- }
241
- // Re-throw other errors
242
- throw error
243
- }
244
- }
245
-
246
- const findIgnoreFilePath = async ( relativePath ) => {
247
- if ( relativePath ) {
248
- const ignoreFilePath = path.join( relativePath, '.gcloudignore' )
249
- if ( fs.existsSync( ignoreFilePath ) ) { // eslint-disable-line security/detect-non-literal-fs-filename
250
- return ignoreFilePath
251
- }
252
- }
253
-
254
- const ignoreFilePath = path.join( process.cwd(), '.gcloudignore' )
255
- if ( fs.existsSync( ignoreFilePath ) ) {
256
- return ignoreFilePath
257
- }
258
-
259
- return null
260
- }
261
-
262
- const copyFilesWithIgnoreConfiguration = async ( sourcePath, destinationPath, ignoreFilePath ) => {
263
- // Ensure sourcePath ends with / so rsync copies contents (not the folder itself) and exclude patterns work correctly
264
- const normalizedSourcePath = sourcePath.endsWith( '/' ) ? sourcePath : `${sourcePath}/`
265
- const command = `rsync -av --delete --exclude-from='${ignoreFilePath}' ${normalizedSourcePath} ${destinationPath}`
266
- await shellCmd( command )
267
- }
268
-
269
- export {
270
- calculateHash,
271
- getArtifactsSchema,
272
- flattenArtifactsSchema,
273
- parseGenericArtifactFileToRemoteRelativePath,
274
- parseGenericArtifactSchemaToRemoteRelativePath,
275
- parseGenericArtifactSchemaToLocalRelativePath,
276
- parseGenericArtifactSchemaToArtifactNameBase,
277
- parseGenericArtifactSchemaToArtifactNameFile,
278
- parseGenericArtifactSchemaToArtifactName,
279
- getMissingRemoteFiles,
280
- listGenericArtifactFiles,
281
- shouldUseIgnoreConfiguration,
282
- findIgnoreFilePath,
283
- copyFilesWithIgnoreConfiguration
284
- }
@@ -1,81 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import path from 'node:path'
4
-
5
- import { program } from 'commander'
6
-
7
- import { warning, log } from '../Utils.mjs'
8
-
9
- import { getArtifactsSchema, flattenArtifactsSchema } from './Utils.mjs'
10
- import { ArtifactTypeEnum } from './Structs.mjs'
11
- import { GenericArtifactPuller } from './ArtifactPuller.mjs'
12
-
13
- program
14
- .name( 'pull-artifact' )
15
- .description( 'Pull artifacts from GCP Artifact Registry' )
16
- .option( '-f, --file-path <file-path>', 'Path to artifacts.yaml file', './artifacts.yaml' )
17
- .option( '-a, --artifact-path <artifact-path>', 'GCP artifact path' )
18
- .parse()
19
-
20
- const options = program.opts()
21
-
22
- async function main() {
23
- const artifactsSchema = await getArtifactsSchema( options.filePath )
24
- const flattenedArtifactsSchema = flattenArtifactsSchema( artifactsSchema )
25
-
26
- let filteredArtifactsSchema = flattenedArtifactsSchema
27
-
28
- if ( options.artifactPath ) {
29
- const artifactPathElements = options.artifactPath.split( '/' )
30
-
31
- if ( artifactPathElements.length !== 5 ) {
32
- warning( 'Invalid artifact path, it must be in the format <project>/<location>/<repository>/<package>/<version>' )
33
- return false
34
- }
35
-
36
- const [ project, location, repository, packageName, version ] = artifactPathElements
37
-
38
- filteredArtifactsSchema = flattenedArtifactsSchema.filter(
39
- artifact => artifact.project === project &&
40
- artifact.location === location &&
41
- artifact.repository === repository &&
42
- artifact.package === packageName &&
43
- artifact.version === version )
44
- }
45
-
46
- let counter = 0
47
-
48
- const pullResults = await Promise.all(
49
- filteredArtifactsSchema.map( async ( artifactSchema ) => {
50
- let puller
51
- switch ( artifactSchema.type ) {
52
- case ArtifactTypeEnum.GENERIC:
53
- puller = new GenericArtifactPuller( path.dirname( options.filePath ), artifactSchema )
54
- break
55
- default:
56
- warning( `Unsupported artifact type "${artifactSchema.type}"` )
57
- return false
58
- }
59
-
60
- if ( !puller ) {
61
- warning( `Unsupported artifact type "${artifactSchema.type}"` )
62
- return false
63
- }
64
-
65
- try {
66
- return await puller.pull()
67
- } catch ( error ) {
68
- warning( `Error pulling artifact "${artifactSchema.name}": ${error.message}` )
69
- return false
70
- }
71
- } )
72
- )
73
-
74
- counter = pullResults.filter( Boolean ).length
75
-
76
- log( `Successfully pulled ${counter}/${filteredArtifactsSchema.length} artifacts` )
77
-
78
- return counter === filteredArtifactsSchema.length
79
- }
80
-
81
- main()
@@ -1,80 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import path from 'node:path'
4
-
5
- import { program } from 'commander'
6
-
7
- import { warning, log } from '../Utils.mjs'
8
-
9
- import { getArtifactsSchema, flattenArtifactsSchema } from './Utils.mjs'
10
- import { ArtifactTypeEnum } from './Structs.mjs'
11
- import { GenericArtifactPusher } from './ArtifactPusher.mjs'
12
-
13
- program
14
- .name( 'push-artifact' )
15
- .description( 'Push artifacts to GCP Artifact Registry' )
16
- .option( '-f, --file-path <file-path>', 'Path to artifacts.yaml file', './artifacts.yaml' )
17
- .option( '-a, --artifact-path <artifact-path>', 'GCP artifact path' )
18
- .parse()
19
-
20
- const options = program.opts()
21
-
22
- async function main() {
23
- const artifactsSchema = await getArtifactsSchema( options.filePath )
24
- const flattenedArtifactsSchema = flattenArtifactsSchema( artifactsSchema )
25
-
26
- let filteredArtifactsSchema = flattenedArtifactsSchema
27
-
28
- if ( options.artifactPath ) {
29
- const artifactPathElements = options.artifactPath.split( '/' )
30
- if ( artifactPathElements.length !== 5 ) {
31
- warning( 'Invalid artifact path, it must be in the format <project>/<location>/<repository>/<package>/<version>' )
32
- return false
33
- }
34
-
35
- const [ project, location, repository, packageName, version ] = artifactPathElements
36
-
37
- filteredArtifactsSchema = flattenedArtifactsSchema.filter(
38
- artifact => artifact.project === project &&
39
- artifact.location === location &&
40
- artifact.repository === repository &&
41
- artifact.package === packageName &&
42
- artifact.version === version )
43
- }
44
-
45
- let counter = 0
46
-
47
- const pushResults = await Promise.all(
48
- filteredArtifactsSchema.map( async ( artifactSchema ) => {
49
- let pusher
50
- switch ( artifactSchema.type ) {
51
- case ArtifactTypeEnum.GENERIC:
52
- pusher = new GenericArtifactPusher( path.dirname( options.filePath ), artifactSchema )
53
- break
54
- default:
55
- warning( `Unsupported artifact type "${artifactSchema.type}"` )
56
- return false
57
- }
58
-
59
- if ( !pusher ) {
60
- warning( `Unsupported artifact type "${artifactSchema.type}"` )
61
- return false
62
- }
63
-
64
- try {
65
- return await pusher.push()
66
- } catch ( error ) {
67
- warning( `Error pushing artifact "${artifactSchema.name}": ${error.message}` )
68
- return false
69
- }
70
- } )
71
- )
72
-
73
- counter = pushResults.filter( Boolean ).length
74
-
75
- log( `Successfully pushed ${counter}/${filteredArtifactsSchema.length} artifacts` )
76
-
77
- return counter === filteredArtifactsSchema.length
78
- }
79
-
80
- main()
package/src/change-up.sh DELETED
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- version="${1:-X.Y.Z}"
5
- date_str=$(date +%F) # e.g., 2025-12-11
6
-
7
- cat <<EOF
8
- ## [$version] - $date_str
9
-
10
- ### Added
11
- -
12
-
13
- ### Changed
14
- -
15
-
16
- ### Deprecated
17
- -
18
-
19
- ### Removed
20
- -
21
-
22
- ### Fixed
23
- -
24
-
25
- ### Migration Notes
26
- -
27
- EOF