@leverege/build-tools 2.93.3-beta.2 → 2.93.3-beta.4
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,11 +1,15 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
import fs from 'node:fs'
|
|
2
3
|
|
|
3
4
|
import { shellCmd, log, err, debug } from '../Utils.mjs'
|
|
4
5
|
|
|
5
6
|
import {
|
|
6
7
|
parseGenericArtifactFileToRemoteRelativePath,
|
|
7
8
|
parseGenericArtifactSchemaToRemoteRelativePath,
|
|
8
|
-
listGenericArtifactFiles
|
|
9
|
+
listGenericArtifactFiles,
|
|
10
|
+
shouldUseIgnoreConfiguration,
|
|
11
|
+
findIgnoreFilePath,
|
|
12
|
+
copyFilesWithIgnoreConfiguration
|
|
9
13
|
} from './Utils.mjs'
|
|
10
14
|
|
|
11
15
|
class ArtifactPusher {
|
|
@@ -29,8 +33,12 @@ class GenericArtifactPusher extends ArtifactPusher {
|
|
|
29
33
|
return false
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
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 {
|
|
34
42
|
let command = ''
|
|
35
43
|
|
|
36
44
|
command = `gcloud artifacts generic upload \
|
|
@@ -40,8 +48,25 @@ class GenericArtifactPusher extends ArtifactPusher {
|
|
|
40
48
|
--package=${this.artifact.package} \
|
|
41
49
|
--version=${this.artifact.version}`
|
|
42
50
|
|
|
51
|
+
let pathToDelete
|
|
52
|
+
|
|
43
53
|
if ( this.artifact.local_path ) {
|
|
44
|
-
const
|
|
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
|
+
|
|
45
70
|
command += ` --source-directory=${localPath}`
|
|
46
71
|
command += ' --skip-existing'
|
|
47
72
|
} else if ( this.artifact.local_file_path ) {
|
|
@@ -66,7 +91,11 @@ class GenericArtifactPusher extends ArtifactPusher {
|
|
|
66
91
|
debug( { command }, '<==Upload Command' )
|
|
67
92
|
|
|
68
93
|
await shellCmd( command )
|
|
69
|
-
|
|
94
|
+
|
|
95
|
+
if ( pathToDelete ) {
|
|
96
|
+
await fs.promises.rm( pathToDelete, { recursive : true } )
|
|
97
|
+
}
|
|
98
|
+
|
|
70
99
|
log( `Successfully pushed artifact: ${this.artifact.name}` )
|
|
71
100
|
|
|
72
101
|
return true
|
package/src/artifacts/Utils.mjs
CHANGED
|
@@ -163,7 +163,6 @@ const calculateHash = async ( path ) => {
|
|
|
163
163
|
hash.update( await fs.promises.readFile( path ) )
|
|
164
164
|
return `${hash.digest( 'base64url' )}=`
|
|
165
165
|
} catch ( error ) {
|
|
166
|
-
console.error( error )
|
|
167
166
|
throw new Error( `Failed to calculate hash for artifact ${path}: ${error.message}` )
|
|
168
167
|
}
|
|
169
168
|
}
|
|
@@ -186,7 +185,7 @@ const listGenericArtifactFiles = async ( artifact ) => {
|
|
|
186
185
|
return files
|
|
187
186
|
}
|
|
188
187
|
|
|
189
|
-
const
|
|
188
|
+
const getMissingRemoteFiles = async ( genericArtifactFiles, genericArtifactSchemaPath, genericArtifactSchema ) => {
|
|
190
189
|
|
|
191
190
|
const expectedRemoteRelativePath = parseGenericArtifactSchemaToRemoteRelativePath( genericArtifactSchema )
|
|
192
191
|
const localRelativePath = parseGenericArtifactSchemaToLocalRelativePath( genericArtifactSchema )
|
|
@@ -221,8 +220,47 @@ const checkGenericArtifactMatch = async ( genericArtifactFiles, genericArtifactS
|
|
|
221
220
|
const actualArray = Array.from( actualFiles )
|
|
222
221
|
const expectedArray = Array.from( expectedFiles )
|
|
223
222
|
|
|
224
|
-
return actualArray.
|
|
225
|
-
|
|
223
|
+
return expectedArray.filter( expected => !actualArray.some( actual => actual.remoteFilePath === expected.remoteFilePath && actual.remoteFileHash === expected.remoteFileHash ) )
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const shouldUseIgnoreConfiguration = async () => {
|
|
227
|
+
let result
|
|
228
|
+
try {
|
|
229
|
+
result = await shellCmd( 'gcloud config get-value gcloudignore/enabled' )
|
|
230
|
+
if ( result.trim() === '' || result.includes( 'has no property' ) ) {
|
|
231
|
+
return false
|
|
232
|
+
}
|
|
233
|
+
return result.trim() === 'true'
|
|
234
|
+
} catch ( error ) {
|
|
235
|
+
if ( error.message && error.message.includes( 'Section [gcloudignore] has no property [enabled]' ) ) {
|
|
236
|
+
return false
|
|
237
|
+
}
|
|
238
|
+
// Re-throw other errors
|
|
239
|
+
throw error
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const findIgnoreFilePath = async ( relativePath ) => {
|
|
244
|
+
if ( relativePath ) {
|
|
245
|
+
const ignoreFilePath = path.join( relativePath, '.gcloudignore' )
|
|
246
|
+
if ( fs.existsSync( ignoreFilePath ) ) {
|
|
247
|
+
return ignoreFilePath
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const ignoreFilePath = path.join( process.cwd(), '.gcloudignore' )
|
|
252
|
+
if ( fs.existsSync( ignoreFilePath ) ) {
|
|
253
|
+
return ignoreFilePath
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return null
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const copyFilesWithIgnoreConfiguration = async ( sourcePath, destinationPath, ignoreFilePath ) => {
|
|
260
|
+
// Ensure sourcePath ends with / so rsync copies contents (not the folder itself) and exclude patterns work correctly
|
|
261
|
+
const normalizedSourcePath = sourcePath.endsWith( '/' ) ? sourcePath : `${sourcePath}/`
|
|
262
|
+
const command = `rsync -av --delete --exclude-from='${ignoreFilePath}' ${normalizedSourcePath} ${destinationPath}`
|
|
263
|
+
await shellCmd( command )
|
|
226
264
|
}
|
|
227
265
|
|
|
228
266
|
export {
|
|
@@ -232,7 +270,12 @@ export {
|
|
|
232
270
|
parseGenericArtifactFileToRemoteRelativePath,
|
|
233
271
|
parseGenericArtifactSchemaToRemoteRelativePath,
|
|
234
272
|
parseGenericArtifactSchemaToLocalRelativePath,
|
|
273
|
+
parseGenericArtifactSchemaToArtifactNameBase,
|
|
274
|
+
parseGenericArtifactSchemaToArtifactNameFile,
|
|
235
275
|
parseGenericArtifactSchemaToArtifactName,
|
|
236
|
-
|
|
237
|
-
listGenericArtifactFiles
|
|
276
|
+
getMissingRemoteFiles,
|
|
277
|
+
listGenericArtifactFiles,
|
|
278
|
+
shouldUseIgnoreConfiguration,
|
|
279
|
+
findIgnoreFilePath,
|
|
280
|
+
copyFilesWithIgnoreConfiguration
|
|
238
281
|
}
|
|
@@ -13,12 +13,8 @@ import { GenericArtifactPuller } from './ArtifactPuller.mjs'
|
|
|
13
13
|
program
|
|
14
14
|
.name( 'pull-artifact' )
|
|
15
15
|
.description( 'Pull artifacts from GCP Artifact Registry' )
|
|
16
|
-
.
|
|
17
|
-
.
|
|
18
|
-
.requiredOption( '-l, --location <location>', 'GCP location' )
|
|
19
|
-
.requiredOption( '-r, --repository <repository>', 'GCP artifact registry repository' )
|
|
20
|
-
.requiredOption( '-n --package <name>', 'GCP artifact registry package name' )
|
|
21
|
-
.requiredOption( '-v, --version <version>', 'GCP artifact registry package version' )
|
|
16
|
+
.option( '-f, --file <path>', 'Path to artifacts.yaml file', './artifacts.yaml' )
|
|
17
|
+
.option( '-a, --artifact <artifact-path>', 'GCP artifact path' )
|
|
22
18
|
.parse()
|
|
23
19
|
|
|
24
20
|
const options = program.opts()
|
|
@@ -26,13 +22,26 @@ const options = program.opts()
|
|
|
26
22
|
async function main() {
|
|
27
23
|
const artifactsSchema = await getArtifactsSchema( options.filePath )
|
|
28
24
|
const flattenedArtifactsSchema = flattenArtifactsSchema( artifactsSchema )
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
|
|
26
|
+
let filteredArtifactsSchema = flattenedArtifactsSchema
|
|
27
|
+
|
|
28
|
+
if ( options.artifact ) {
|
|
29
|
+
const artifactPathElements = options.artifact.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
|
+
}
|
|
36
45
|
|
|
37
46
|
let counter = 0
|
|
38
47
|
|
|
@@ -65,6 +74,8 @@ async function main() {
|
|
|
65
74
|
counter = pullResults.filter( Boolean ).length
|
|
66
75
|
|
|
67
76
|
log( `Successfully pulled ${counter}/${filteredArtifactsSchema.length} artifacts` )
|
|
77
|
+
|
|
78
|
+
return counter === filteredArtifactsSchema.length
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
main()
|
|
@@ -13,12 +13,8 @@ import { GenericArtifactPusher } from './ArtifactPusher.mjs'
|
|
|
13
13
|
program
|
|
14
14
|
.name( 'push-artifact' )
|
|
15
15
|
.description( 'Push artifacts to GCP Artifact Registry' )
|
|
16
|
-
.
|
|
17
|
-
.
|
|
18
|
-
.requiredOption( '-l, --location <location>', 'GCP location' )
|
|
19
|
-
.requiredOption( '-r, --repository <repository>', 'GCP artifact registry repository' )
|
|
20
|
-
.requiredOption( '-n --package <name>', 'GCP artifact registry package name' )
|
|
21
|
-
.requiredOption( '-v, --version <version>', 'GCP artifact registry package version' )
|
|
16
|
+
.option( '-f, --file <path>', 'Path to artifacts.yaml file', './artifacts.yaml' )
|
|
17
|
+
.option( '-a, --artifact <artifact-path>', 'GCP artifact path' )
|
|
22
18
|
.parse()
|
|
23
19
|
|
|
24
20
|
const options = program.opts()
|
|
@@ -26,13 +22,25 @@ const options = program.opts()
|
|
|
26
22
|
async function main() {
|
|
27
23
|
const artifactsSchema = await getArtifactsSchema( options.filePath )
|
|
28
24
|
const flattenedArtifactsSchema = flattenArtifactsSchema( artifactsSchema )
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
|
|
26
|
+
let filteredArtifactsSchema = flattenedArtifactsSchema
|
|
27
|
+
|
|
28
|
+
if ( options.artifact ) {
|
|
29
|
+
const artifactPathElements = options.artifact.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
|
+
}
|
|
36
44
|
|
|
37
45
|
let counter = 0
|
|
38
46
|
|
|
@@ -65,6 +73,8 @@ async function main() {
|
|
|
65
73
|
counter = pushResults.filter( Boolean ).length
|
|
66
74
|
|
|
67
75
|
log( `Successfully pushed ${counter}/${filteredArtifactsSchema.length} artifacts` )
|
|
76
|
+
|
|
77
|
+
return counter === filteredArtifactsSchema.length
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
main()
|