@leverege/build-tools 2.122.0 → 2.124.0
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 +7 -6
- package/src/Utils.mjs +1 -1
- package/src/build-cnpg-image.mjs +27 -6
- package/src/close-dependabot-prs.mjs +148 -0
- package/src/dashboard/json/tpi/tpi-ply-tolerancing.json +2968 -0
- package/src/github-actions-it.mjs +7 -0
- package/src/helm-charts/cnpg-db-tsdb-basic/cluster.yaml.ovh +23 -0
- package/src/helm-charts/db-curator/values-local.yaml +1 -9
- package/src/helm-charts/prom-operator/prometheus-stack.yaml.ovh +1 -1
- package/src/helm-charts/transponder-bq/values-local.yaml +0 -3
- package/src/helm-charts/transponder-dh/values-local.yaml +0 -3
- package/src/helm-charts/transponder-rt/values-local.yaml +0 -3
- package/src/helm-charts/transponder-tsdb/values-local.yaml +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.124.0",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"chart-compass": "src/chart-compass.mjs",
|
|
26
26
|
"chart-to-registry": "src/chart-to-registry.mjs",
|
|
27
27
|
"clone-cnpg-from-snapshot": "src/clone-cnpg-from-snapshot.mjs",
|
|
28
|
+
"close-dependabot-prs": "src/close-dependabot-prs.mjs",
|
|
28
29
|
"count-lines-of-code": "src/count-lines-of-code.mjs",
|
|
29
30
|
"dashboard": "src/dashboard/dashboard.mjs",
|
|
30
31
|
"decrypt-secrets": "src/decrypt-secrets.sh",
|
|
@@ -103,14 +104,14 @@
|
|
|
103
104
|
"glob": "^13.0.6",
|
|
104
105
|
"googleapis": "^176.0.0",
|
|
105
106
|
"handlebars": "^4.7.9",
|
|
106
|
-
"ignore": "^7.0.
|
|
107
|
-
"inquirer": "^14.2.
|
|
108
|
-
"js-yaml": "^4.2
|
|
107
|
+
"ignore": "^7.0.9",
|
|
108
|
+
"inquirer": "^14.2.2",
|
|
109
|
+
"js-yaml": "^4.3.2",
|
|
109
110
|
"jsdoc": "^4.0.5",
|
|
110
111
|
"ms": "^2.1.3",
|
|
111
112
|
"npm-registry-fetch": "^20.0.1",
|
|
112
113
|
"ora": "^9.4.1",
|
|
113
|
-
"p-limit": "^7.3.
|
|
114
|
+
"p-limit": "^7.3.2",
|
|
114
115
|
"package-up": "^5.0.0",
|
|
115
116
|
"readline-sync": "^1.4.10",
|
|
116
117
|
"semver": "^7.8.5",
|
|
@@ -127,7 +128,7 @@
|
|
|
127
128
|
"@leverege/eslint-config-leverege": "^9",
|
|
128
129
|
"chai": "^6.2.2",
|
|
129
130
|
"eslint": "^9",
|
|
130
|
-
"mocha": "^
|
|
131
|
+
"mocha": "^12.0.0",
|
|
131
132
|
"npm": "^12.0.2"
|
|
132
133
|
},
|
|
133
134
|
"allowScripts": {
|
package/src/Utils.mjs
CHANGED
|
@@ -740,7 +740,7 @@ export const analyzeRepository = async ( giveGuidance ) => {
|
|
|
740
740
|
}
|
|
741
741
|
|
|
742
742
|
const containerName = closestPackageJson?.name.replace( /^@[^/]+\//, '' ) || rootPyProjectToml?.project.name
|
|
743
|
-
const imagePlatform = closestPackageJson?.leverege.imagePlatform || rootPyProjectToml?.leverege['image-platform'] || [ 'linux/amd64' ]
|
|
743
|
+
const imagePlatform = closestPackageJson?.leverege.imagePlatform || rootPyProjectToml?.leverege['image-platform'] || [ 'linux/amd64', 'linux/arm64' ]
|
|
744
744
|
const artifactRegistry = closestPackageJson?.leverege.registry || rootPyProjectToml?.leverege.registry
|
|
745
745
|
const artifactProject = closestPackageJson?.artifactRegistry.project || rootPyProjectToml?.artifactRegistry.project || 'unknown'
|
|
746
746
|
const packageVersion = `v${closestPackageJson?.version || rootPyProjectToml?.project.version}`
|
package/src/build-cnpg-image.mjs
CHANGED
|
@@ -85,6 +85,22 @@ const LEVEREGE_REGISTRY = 'us-docker.pkg.dev/leverege-registry/system/images/lev
|
|
|
85
85
|
const LEVEREGE_IMAGE_TAG = `${PG_VERSION}-cnpg-lvrg-${subTag}`
|
|
86
86
|
const LEVEREGE_IMAGE_NAME_WITH_TAG = `${LEVEREGE_REGISTRY}:${LEVEREGE_IMAGE_TAG}`
|
|
87
87
|
|
|
88
|
+
const CLOUDBUILD_YAML_TEMPLATE = `steps:
|
|
89
|
+
- name: 'gcr.io/cloud-builders/docker'
|
|
90
|
+
entrypoint: bash
|
|
91
|
+
args:
|
|
92
|
+
- '-c'
|
|
93
|
+
- |
|
|
94
|
+
docker run --privileged --rm tonistiigi/binfmt --install all
|
|
95
|
+
docker buildx create --use --name builder --driver docker-container
|
|
96
|
+
docker buildx inspect --bootstrap
|
|
97
|
+
docker buildx build \\
|
|
98
|
+
--platform linux/amd64,linux/arm64 \\
|
|
99
|
+
--tag {{IMAGE_TAG}} \\
|
|
100
|
+
--push \\
|
|
101
|
+
/workspace
|
|
102
|
+
`
|
|
103
|
+
|
|
88
104
|
const DOCKERFILE_TEMPLATE = `
|
|
89
105
|
FROM ghcr.io/cloudnative-pg/postgresql:{{PG_VERSION}}-bookworm
|
|
90
106
|
|
|
@@ -130,22 +146,27 @@ const checkExistingImage = async ( imageName ) => {
|
|
|
130
146
|
|
|
131
147
|
// Build and push Docker image
|
|
132
148
|
const buildAndPushImage = async () => {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
149
|
+
const dockerfileTemplate = Handlebars.compile( DOCKERFILE_TEMPLATE )
|
|
150
|
+
const cloudbuildTemplate = Handlebars.compile( CLOUDBUILD_YAML_TEMPLATE )
|
|
151
|
+
|
|
152
|
+
const renderedDockerfile = dockerfileTemplate( { PG_VERSION } )
|
|
153
|
+
const renderedCloudbuild = cloudbuildTemplate( { IMAGE_TAG : LEVEREGE_IMAGE_NAME_WITH_TAG } )
|
|
154
|
+
debug( { renderedDockerfile, renderedCloudbuild }, '<==Build files' )
|
|
136
155
|
|
|
137
156
|
// Create a temporary directory to build from
|
|
138
157
|
const buildDir = fs.mkdtempSync( path.join( os.tmpdir(), 'docker-build-' ) )
|
|
139
158
|
const dockerfilePath = path.join( buildDir, 'Dockerfile' )
|
|
159
|
+
const cloudbuildPath = path.join( buildDir, 'cloudbuild.yaml' )
|
|
140
160
|
|
|
141
161
|
try {
|
|
142
162
|
fs.writeFileSync( dockerfilePath, renderedDockerfile ) // eslint-disable-line security/detect-non-literal-fs-filename
|
|
163
|
+
fs.writeFileSync( cloudbuildPath, renderedCloudbuild ) // eslint-disable-line security/detect-non-literal-fs-filename
|
|
143
164
|
|
|
144
|
-
log( chalk.yellow( '\nBuilding Docker image...' ) )
|
|
165
|
+
log( chalk.yellow( '\nBuilding Docker image (multi-arch: linux/amd64, linux/arm64)...' ) )
|
|
145
166
|
const cloudBuildSubmit = 'gcloud builds submit --project leverege-registry'
|
|
146
167
|
const cloudBuildLog = '--gcs-log-dir gs://leverege-registry_cloudbuild/log'
|
|
147
|
-
const
|
|
148
|
-
await shellCmd( `${cloudBuildSubmit} ${cloudBuildLog} ${
|
|
168
|
+
const configFlag = `--config ${cloudbuildPath}`
|
|
169
|
+
await shellCmd( `${cloudBuildSubmit} ${cloudBuildLog} ${configFlag} ${buildDir}`, { stdio : 'inherit' } )
|
|
149
170
|
} finally {
|
|
150
171
|
// Ensure cleanup even if the build fails
|
|
151
172
|
fs.rmSync( buildDir, { recursive : true, force : true } )
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { $ } from 'zx'
|
|
4
|
+
import { program } from 'commander'
|
|
5
|
+
import chalk from 'chalk'
|
|
6
|
+
|
|
7
|
+
import { enableDebug, errorExit, log } from './Utils.mjs'
|
|
8
|
+
|
|
9
|
+
$.verbose = false
|
|
10
|
+
|
|
11
|
+
const DEFAULT_OWNER = 'Leverege'
|
|
12
|
+
|
|
13
|
+
const COMMENT = (
|
|
14
|
+
'Closing in favor of the new grouped Dependabot config (patch/minor ' +
|
|
15
|
+
'updates now batch into a single PR). Not a rejection of this specific ' +
|
|
16
|
+
'bump - Dependabot will re-propose it as part of a grouped PR on its ' +
|
|
17
|
+
'next scan.'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const TITLE_RE = /^Bump (\S+) from (\S+) to (\S+)$/
|
|
21
|
+
|
|
22
|
+
program
|
|
23
|
+
.name( 'close-dependabot-prs' )
|
|
24
|
+
.description( chalk.green( 'Close open Dependabot PRs superseded by a newly-grouped dependabot.yml config' ) )
|
|
25
|
+
.argument( '<repos...>', 'repo names - bare name uses --owner, or pass owner/repo to override' )
|
|
26
|
+
.option( '--owner <name>', 'GitHub org/owner for bare repo names', DEFAULT_OWNER )
|
|
27
|
+
.option( '--dry-run', 'show what would be closed without closing anything' )
|
|
28
|
+
.option( '--debug', 'Enable debug logging' )
|
|
29
|
+
.addHelpText( 'after', `
|
|
30
|
+
${chalk.yellow( 'Examples:' )}
|
|
31
|
+
${chalk.green( 'close-dependabot-prs array-util base62-util' )}
|
|
32
|
+
${chalk.green( 'close-dependabot-prs --dry-run cache' )}
|
|
33
|
+
${chalk.green( 'close-dependabot-prs --owner SomeOtherOrg some-repo' )}
|
|
34
|
+
|
|
35
|
+
${chalk.yellow( 'Notes:' )}
|
|
36
|
+
Closes open Dependabot PRs that are superseded by a newly-added groups:
|
|
37
|
+
config in dependabot.yml (patch/minor updates now batch into one PR).
|
|
38
|
+
Leaves major-version PRs open, since they aren't covered by grouping and
|
|
39
|
+
closing them risks Dependabot never re-proposing that exact version.
|
|
40
|
+
|
|
41
|
+
Skips any repo whose dependabot.yml has no groups: block at all - closing
|
|
42
|
+
PRs there would lose them rather than get them re-proposed.
|
|
43
|
+
|
|
44
|
+
Requires the gh CLI, authenticated.
|
|
45
|
+
` )
|
|
46
|
+
.parse()
|
|
47
|
+
|
|
48
|
+
const opts = program.opts()
|
|
49
|
+
if ( opts.debug ) { enableDebug(); $.verbose = true }
|
|
50
|
+
|
|
51
|
+
const repos = program.args.map( repo => ( repo.includes( '/' ) ? repo : `${opts.owner}/${repo}` ) )
|
|
52
|
+
|
|
53
|
+
if ( repos.length === 0 ) {
|
|
54
|
+
errorExit( 'No repos provided.' )
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------- Helpers ----------
|
|
58
|
+
|
|
59
|
+
async function hasGroupingConfigured( repo ) {
|
|
60
|
+
let stdout
|
|
61
|
+
try {
|
|
62
|
+
( { stdout } = await $`gh api repos/${repo}/contents/.github/dependabot.yml --jq .content` )
|
|
63
|
+
} catch {
|
|
64
|
+
return null // couldn't fetch - treat as unknown, caller should skip
|
|
65
|
+
}
|
|
66
|
+
const content = Buffer.from( stdout.trim(), 'base64' ).toString( 'utf8' )
|
|
67
|
+
return content.includes( 'groups:' )
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function versionTuple( v ) {
|
|
71
|
+
const m = v.match( /^(\d+(?:\.\d+)*)/ )
|
|
72
|
+
if ( !m ) return null
|
|
73
|
+
return m[1].split( '.' ).map( Number )
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function classifyBump( fromV, toV ) {
|
|
77
|
+
const a = versionTuple( fromV )
|
|
78
|
+
const b = versionTuple( toV )
|
|
79
|
+
if ( !a || !b ) return 'unknown'
|
|
80
|
+
const length = Math.max( a.length, b.length )
|
|
81
|
+
while ( a.length < length ) a.push( 0 )
|
|
82
|
+
while ( b.length < length ) b.push( 0 )
|
|
83
|
+
if ( a[0] !== b[0] ) return 'major'
|
|
84
|
+
if ( a.length > 1 && a[1] !== b[1] ) return 'minor'
|
|
85
|
+
return 'patch'
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function openDependabotPrs( repo ) {
|
|
89
|
+
const { stdout } = await $`gh pr list --repo ${repo} --state open --search head:dependabot --json number,title,headRefName`
|
|
90
|
+
return JSON.parse( stdout )
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function processRepo( repo, dryRun ) {
|
|
94
|
+
log( `\n=== ${repo} ===` )
|
|
95
|
+
const grouped = await hasGroupingConfigured( repo )
|
|
96
|
+
if ( grouped === null ) {
|
|
97
|
+
log( ' ! could not read .github/dependabot.yml - skipping' )
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
if ( !grouped ) {
|
|
101
|
+
log(
|
|
102
|
+
' ! no `groups:` block found in dependabot.yml - skipping ' +
|
|
103
|
+
'(closing PRs here would lose them, not get them re-proposed)'
|
|
104
|
+
)
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const prs = await openDependabotPrs( repo )
|
|
109
|
+
if ( prs.length === 0 ) {
|
|
110
|
+
log( ' no open dependabot PRs' )
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let closedCount = 0
|
|
115
|
+
let keptCount = 0
|
|
116
|
+
let skippedCount = 0
|
|
117
|
+
|
|
118
|
+
for ( const pr of prs ) {
|
|
119
|
+
const m = pr.title.match( TITLE_RE )
|
|
120
|
+
if ( !m ) {
|
|
121
|
+
skippedCount++
|
|
122
|
+
log( ` skip #${pr.number} (title didn't match expected pattern) ${pr.title}` )
|
|
123
|
+
continue
|
|
124
|
+
}
|
|
125
|
+
const [ , , fromV, toV ] = m
|
|
126
|
+
const bumpType = classifyBump( fromV, toV )
|
|
127
|
+
if ( bumpType === 'patch' || bumpType === 'minor' ) {
|
|
128
|
+
closedCount++
|
|
129
|
+
log( ` close #${String( pr.number ).padEnd( 4 )} ${bumpType.padEnd( 7 )} ${pr.title}` )
|
|
130
|
+
if ( !dryRun ) {
|
|
131
|
+
// eslint-disable-next-line no-await-in-loop
|
|
132
|
+
await $`gh pr close ${pr.number} --repo ${repo} --comment ${COMMENT}`
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
keptCount++
|
|
136
|
+
log( ` keep #${String( pr.number ).padEnd( 4 )} ${bumpType.padEnd( 7 )} ${pr.title}` )
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
log( ` -> ${closedCount} closed, ${keptCount} left open (major), ${skippedCount} skipped` )
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ---------- Run ----------
|
|
144
|
+
|
|
145
|
+
for ( const repo of repos ) {
|
|
146
|
+
// eslint-disable-next-line no-await-in-loop
|
|
147
|
+
await processRepo( repo, opts.dryRun )
|
|
148
|
+
}
|