newrelic 7.1.2 → 7.3.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/NEWS.md +97 -0
- package/THIRD_PARTY_NOTICES.md +33 -2
- package/bin/test-naming-rules.js +4 -4
- package/index.js +4 -2
- package/lib/agent.js +4 -0
- package/lib/collector/api.js +45 -18
- package/lib/collector/facts.js +22 -8
- package/lib/collector/http-agents.js +20 -7
- package/lib/collector/remote-method.js +32 -9
- package/lib/config/index.js +48 -39
- package/lib/feature_flags.js +6 -2
- package/lib/grpc/connection.js +39 -15
- package/lib/instrumentation/core/async_hooks.js +101 -14
- package/lib/instrumentation/core/http.js +5 -0
- package/lib/instrumentation/core/timers.js +6 -1
- package/lib/metrics/names.js +7 -1
- package/lib/shim/shim.js +6 -1
- package/lib/spans/create-span-event-aggregator.js +1 -0
- package/lib/spans/span-event.js +6 -3
- package/lib/spans/streaming-span-event.js +6 -3
- package/lib/transaction/index.js +36 -0
- package/newrelic.js +1 -1
- package/package.json +19 -7
- package/CONTRIBUTING.md +0 -135
- package/Migration Guide.md +0 -271
- package/ROADMAP_Node.md +0 -24
- package/SECURITY.md +0 -5
- package/THIRD_PARTY_NOTICES_ADDENDUM.md +0 -213
- package/bin/ca-gen.js +0 -91
- package/bin/cassandra-setup.sh +0 -11
- package/bin/check-workflow-run.js +0 -74
- package/bin/clean.sh +0 -18
- package/bin/compare-bench-results.js +0 -172
- package/bin/create-release.js +0 -74
- package/bin/docker-env-vars.sh +0 -15
- package/bin/docker-services.sh +0 -49
- package/bin/generate-release-notes.js +0 -126
- package/bin/github.js +0 -119
- package/bin/publish-docs.sh +0 -16
- package/bin/run-bench.js +0 -137
- package/bin/run-versioned-tests.sh +0 -32
- package/bin/smoke.sh +0 -8
- package/bin/ssl.sh +0 -87
- package/bin/travis-install-gcc5.sh +0 -13
- package/bin/travis-install-mongo.sh +0 -16
- package/bin/travis-node.sh +0 -57
- package/bin/travis-setup.sh +0 -52
- package/bin/update-ca-bundle.sh +0 -20
- package/bin/update-cats.sh +0 -8
- package/bin/update-changelog-version.js +0 -68
- package/jsdoc-conf.json +0 -18
- package/third_party_manifest.json +0 -619
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Github = require('./github')
|
|
4
|
-
|
|
5
|
-
const SUCCESS_MSG = '*** [OK] ***'
|
|
6
|
-
|
|
7
|
-
const formatRun = (run) => {
|
|
8
|
-
return {
|
|
9
|
-
name: run.name,
|
|
10
|
-
repository: run.repository.name,
|
|
11
|
-
repoOwner: run.repository.owner.login,
|
|
12
|
-
branch: run.head_branch,
|
|
13
|
-
status: run.status,
|
|
14
|
-
url: run.url,
|
|
15
|
-
workflow_id: run.workflow_id,
|
|
16
|
-
event: run.event
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function checkWorkflowRun(repoOwner, branch) {
|
|
21
|
-
const github = new Github(repoOwner)
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const results = {
|
|
25
|
-
ci: false,
|
|
26
|
-
smokeTest: false
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const latestRun = await github.getLatestWorkflowRun('ci-workflow.yml', branch)
|
|
30
|
-
|
|
31
|
-
if (latestRun === undefined) {
|
|
32
|
-
console.log('No ci workflow run found.')
|
|
33
|
-
} else {
|
|
34
|
-
console.log('CI workflow run details: ', JSON.stringify(formatRun(latestRun)))
|
|
35
|
-
if (latestRun.status === 'completed' && latestRun.conclusion === 'success') {
|
|
36
|
-
results.ci = true
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const latestSmokeTestRun = await github.getLatestWorkflowRun('smoke-test-workflow.yml', branch)
|
|
41
|
-
|
|
42
|
-
if (latestSmokeTestRun === undefined) {
|
|
43
|
-
console.log('No smoke test workflow run found.')
|
|
44
|
-
} else {
|
|
45
|
-
console.log('Smoke-test workflow run details: ', JSON.stringify(formatRun(latestSmokeTestRun)))
|
|
46
|
-
|
|
47
|
-
if (latestSmokeTestRun.status === 'completed' && latestSmokeTestRun.conclusion === 'success') {
|
|
48
|
-
results.smokeTest = true
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (results.ci && results.smokeTest) {
|
|
53
|
-
console.log(SUCCESS_MSG)
|
|
54
|
-
console.log('Latest ci and smoke-test runs were successful!')
|
|
55
|
-
return true
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!results.ci) {
|
|
59
|
-
console.log('Latest ci workflow run result was not \'completed\' and \'success\'.')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!results.smokeTest) {
|
|
63
|
-
console.log('Latest smoke-test workflow run result was not \'completed\' and \'success\'.')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return false
|
|
67
|
-
} catch (err) {
|
|
68
|
-
console.error(err)
|
|
69
|
-
|
|
70
|
-
return false
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
module.exports = checkWorkflowRun
|
package/bin/clean.sh
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#! /bin/sh
|
|
2
|
-
|
|
3
|
-
# Copyright 2020 New Relic Corporation. All rights reserved.
|
|
4
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
|
|
6
|
-
SSLKEY="test/lib/test-key.key"
|
|
7
|
-
CACERT="test/lib/ca-certificate.crt"
|
|
8
|
-
CAINDEX="test/lib/ca-index"
|
|
9
|
-
CASERIAL="test/lib/ca-serial"
|
|
10
|
-
CERTIFICATE="test/lib/self-signed-test-certificate.crt"
|
|
11
|
-
|
|
12
|
-
find . -depth -type d -name node_modules -print0 | xargs -0 rm -rf
|
|
13
|
-
find . -name package-lock.json -print0 | xargs -0 rm -rf
|
|
14
|
-
find . -name newrelic_agent.log -print0 | xargs -0 rm -rf
|
|
15
|
-
rm -rf npm-debug.log newrelic_agent.log .coverage_data cover_html
|
|
16
|
-
rm -rf $SSLKEY $CACERT $CAINDEX $CASERIAL $CERTIFICATE
|
|
17
|
-
rm -rf test/lib/*.old test/lib/*.attr
|
|
18
|
-
rm -rf docs/
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
/* eslint-disable no-console */
|
|
8
|
-
|
|
9
|
-
const async = require('async')
|
|
10
|
-
const fs = require('fs')
|
|
11
|
-
|
|
12
|
-
if (process.argv.length !== 4) {
|
|
13
|
-
console.log('Usage: %s %s <baseline> <upstream>', process.argv[0], process.argv[1])
|
|
14
|
-
console.log(' <baseline> JSON file containing benchmark results for upstream')
|
|
15
|
-
console.log(' upstream comparison.')
|
|
16
|
-
console.log(' <downstream> JSON file containing benchmark results from')
|
|
17
|
-
console.log(' downstream branch to compare against base.')
|
|
18
|
-
process.exit(1)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async.map(process.argv.slice(2), (file, cb) => {
|
|
22
|
-
fs.readFile(file, {encoding: 'utf8'}, (err, data) => {
|
|
23
|
-
if (err) {
|
|
24
|
-
return cb(err)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
let parsed = null
|
|
28
|
-
try {
|
|
29
|
-
parsed = JSON.parse(data)
|
|
30
|
-
} catch (parseError) {
|
|
31
|
-
return cb(parseError)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
cb(null, parsed)
|
|
35
|
-
})
|
|
36
|
-
}, (err, resultFiles) => {
|
|
37
|
-
if (err) {
|
|
38
|
-
console.log('Failed to load files.')
|
|
39
|
-
console.log(err)
|
|
40
|
-
process.exit(2)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const baseline = resultFiles[0]
|
|
44
|
-
const downstream = resultFiles[1]
|
|
45
|
-
|
|
46
|
-
const baselineFiles = Object.keys(baseline)
|
|
47
|
-
const downstreamFiles = Object.keys(downstream)
|
|
48
|
-
const warnings = []
|
|
49
|
-
|
|
50
|
-
diffArrays(baselineFiles, downstreamFiles).forEach((file) => {
|
|
51
|
-
warnings.push(`- **WARNING**: File "${file}" in base but not branch.`)
|
|
52
|
-
})
|
|
53
|
-
diffArrays(downstreamFiles, baselineFiles).forEach((file) => {
|
|
54
|
-
warnings.push(`- **NOTE**: File "${file}" in branch but not base.`)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
let allPassing = true
|
|
58
|
-
const details = baselineFiles.sort().map((testFile) => {
|
|
59
|
-
const base = baseline[testFile]
|
|
60
|
-
const down = downstream[testFile]
|
|
61
|
-
|
|
62
|
-
if (!down) {
|
|
63
|
-
return [
|
|
64
|
-
'<details>',
|
|
65
|
-
`<summary>${testFile} file missing from branch</summary>`,
|
|
66
|
-
'',
|
|
67
|
-
'</details>'
|
|
68
|
-
].join('\n')
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let filePassing = true
|
|
72
|
-
const baseTests = Object.keys(base)
|
|
73
|
-
const downTests = Object.keys(down)
|
|
74
|
-
|
|
75
|
-
diffArrays(baseTests, downTests).forEach((test) => {
|
|
76
|
-
warnings.push(`- **WARNING**: Test "${test}" in base but not branch.`)
|
|
77
|
-
})
|
|
78
|
-
diffArrays(downTests, baseTests).forEach((test) => {
|
|
79
|
-
warnings.push(`- **NOTE**: Test "${test}" in branch but not base.`)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const results = baseTests.sort().map((test) => {
|
|
83
|
-
const passes = compareResults(base[test], down[test])
|
|
84
|
-
filePassing = filePassing && passes
|
|
85
|
-
|
|
86
|
-
return [
|
|
87
|
-
'<details>',
|
|
88
|
-
`<summary>${test}: ${passMark(passes)}</summary>`,
|
|
89
|
-
'',
|
|
90
|
-
formatResults(base[test], down[test]),
|
|
91
|
-
'</details>',
|
|
92
|
-
''
|
|
93
|
-
].join('\n')
|
|
94
|
-
}).join('\n')
|
|
95
|
-
allPassing = allPassing && filePassing
|
|
96
|
-
|
|
97
|
-
return [
|
|
98
|
-
'<details>',
|
|
99
|
-
`<summary>${testFile}: ${passMark(filePassing)}</summary>`,
|
|
100
|
-
'',
|
|
101
|
-
results,
|
|
102
|
-
'',
|
|
103
|
-
'-----------------------------------------------------------------------',
|
|
104
|
-
'</details>'
|
|
105
|
-
].join('\n')
|
|
106
|
-
}).join('\n\n')
|
|
107
|
-
|
|
108
|
-
if (warnings.length) {
|
|
109
|
-
console.log('### WARNINGS')
|
|
110
|
-
console.log(warnings.join('\n'))
|
|
111
|
-
console.log('')
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
console.log(`### Benchmark Results: ${passMark(allPassing)}`)
|
|
115
|
-
console.log('')
|
|
116
|
-
console.log('### Details')
|
|
117
|
-
console.log('_Lower is better._')
|
|
118
|
-
console.log(details)
|
|
119
|
-
|
|
120
|
-
if (!allPassing) {
|
|
121
|
-
process.exitCode = -1
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
function diffArrays(a, b) {
|
|
126
|
-
return a.filter((elem) => !b.includes(elem))
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function compareResults(base, down) {
|
|
130
|
-
const delta = down.mean - base.mean
|
|
131
|
-
const deltaPercent = delta / base.mean
|
|
132
|
-
if (Math.abs(delta) < 0.1) {
|
|
133
|
-
return deltaPercent < 100
|
|
134
|
-
}
|
|
135
|
-
return deltaPercent < 2
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function passMark(passes) {
|
|
139
|
-
return passes ? '✔' : '✘'
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function formatResults(base, down) {
|
|
143
|
-
return [
|
|
144
|
-
'Field | Upstream (ms) | Downstream (ms) | Delta (ms) | Delta (%)',
|
|
145
|
-
'----- | ------------: | --------------: | ---------: | --------:',
|
|
146
|
-
formatField('numSamples'),
|
|
147
|
-
formatField('mean'),
|
|
148
|
-
formatField('stdDev'),
|
|
149
|
-
formatField('max'),
|
|
150
|
-
formatField('min'),
|
|
151
|
-
formatField('5thPercentile'),
|
|
152
|
-
formatField('95thPercentile'),
|
|
153
|
-
formatField('median')
|
|
154
|
-
].join('\n')
|
|
155
|
-
|
|
156
|
-
function formatField(field) {
|
|
157
|
-
const baseValue = base[field]
|
|
158
|
-
const downValue = down[field]
|
|
159
|
-
const diffValue = downValue - baseValue
|
|
160
|
-
const diffPercent = (100 * diffValue / baseValue).toFixed(2)
|
|
161
|
-
const prefix = diffValue >= 0 ? '+' : ''
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
`${field} | ${fixValue(baseValue)} | ${fixValue(downValue)} |` +
|
|
165
|
-
` ${fixValue(diffValue)} | ${prefix}${diffPercent}%`
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function fixValue(value) {
|
|
170
|
-
return value % 1 ? value.toFixed(5) : value
|
|
171
|
-
}
|
|
172
|
-
}
|
package/bin/create-release.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const {exec} = require('child_process')
|
|
4
|
-
const checkWorkflowRun = require('./check-workflow-run')
|
|
5
|
-
const {program, Option} = require('commander')
|
|
6
|
-
|
|
7
|
-
const ERROR_MSG = '! [ERROR] !\n'
|
|
8
|
-
|
|
9
|
-
// Add command line options
|
|
10
|
-
program.option('-b, --branch <branch>', 'release branch', 'main')
|
|
11
|
-
|
|
12
|
-
program.addOption(new Option('-r, --release-type <releaseType>', 'release type')
|
|
13
|
-
.choices(['patch', 'minor', 'major']))
|
|
14
|
-
|
|
15
|
-
program.option('-m, --major-release', 'create a major release. (release-type option must be set to \'major\')')
|
|
16
|
-
|
|
17
|
-
program.option('-o, --repo-owner <repoOwner>', 'repository owner', 'newrelic')
|
|
18
|
-
|
|
19
|
-
async function createRelease() {
|
|
20
|
-
// Parse commandline options inputs
|
|
21
|
-
program.parse()
|
|
22
|
-
|
|
23
|
-
const options = program.opts()
|
|
24
|
-
|
|
25
|
-
// TODO: rework to use program.requiredOption
|
|
26
|
-
if (!options.releaseType) {
|
|
27
|
-
console.log('FAILURE: release type required.')
|
|
28
|
-
process.exit(1)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (options.releaseType === 'major' && !options.majorRelease) {
|
|
32
|
-
console.log('WARNING: you must set the \'-m\' flag to create a major release.\nExiting...')
|
|
33
|
-
process.exit(1)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (options.majorRelease && options.releaseType !== 'major') {
|
|
37
|
-
console.log(`WARNING: ignoring \'-m, --major-release\' option as release type set to ${options.rel}.`)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const releaseType = options.releaseType
|
|
41
|
-
const branch = options.branch ? options.branch.replace('refs/heads/', '') : null
|
|
42
|
-
const repoOwner = options.repoOwner ? options.repoOwner : null
|
|
43
|
-
|
|
44
|
-
try {
|
|
45
|
-
const passesWorkflowChecks = await checkWorkflowRun(repoOwner, branch)
|
|
46
|
-
|
|
47
|
-
if (!passesWorkflowChecks) {
|
|
48
|
-
process.exit(1)
|
|
49
|
-
}
|
|
50
|
-
} catch (err) {
|
|
51
|
-
console.log(err)
|
|
52
|
-
|
|
53
|
-
process.exit(1)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log('Starting npm version and pushing tags')
|
|
57
|
-
exec(`npm version ${releaseType} && git push origin ${branch} && git push --tags`, (err, stdout) => {
|
|
58
|
-
if (err) {
|
|
59
|
-
console.log(ERROR_MSG, err)
|
|
60
|
-
|
|
61
|
-
process.exit(1)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (stdout) {
|
|
65
|
-
console.log(stdout)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
console.log('DONE')
|
|
69
|
-
|
|
70
|
-
process.exit(0)
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
createRelease()
|
package/bin/docker-env-vars.sh
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#! /bin/bash
|
|
2
|
-
|
|
3
|
-
# Copyright 2020 New Relic Corporation. All rights reserved.
|
|
4
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
|
|
6
|
-
IP=`docker-machine ip default 2>/dev/null`
|
|
7
|
-
|
|
8
|
-
export NR_NODE_TEST_CASSANDRA_HOST=$IP
|
|
9
|
-
export NR_NODE_TEST_MEMCACHED_HOST=$IP
|
|
10
|
-
export NR_NODE_TEST_MONGODB_HOST=$IP
|
|
11
|
-
export NR_NODE_TEST_MYSQL_HOST=$IP
|
|
12
|
-
export NR_NODE_TEST_ORACLE_HOST=$IP
|
|
13
|
-
export NR_NODE_TEST_POSTGRES_HOST=$IP
|
|
14
|
-
export NR_NODE_TEST_REDIS_HOST=$IP
|
|
15
|
-
export NR_NODE_TEST_RABBIT_HOST=$IP
|
package/bin/docker-services.sh
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#! /bin/bash
|
|
2
|
-
|
|
3
|
-
# Copyright 2020 New Relic Corporation. All rights reserved.
|
|
4
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
|
|
6
|
-
if docker ps -a | grep -q "nr_node_memcached"; then
|
|
7
|
-
docker start nr_node_memcached;
|
|
8
|
-
else
|
|
9
|
-
docker run -d --name nr_node_memcached -p 11211:11211 memcached;
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
if docker ps -a | grep -q "nr_node_mongodb"; then
|
|
13
|
-
docker start nr_node_mongodb;
|
|
14
|
-
else
|
|
15
|
-
docker run -d --name nr_node_mongodb -p 27017:27017 library/mongo:2;
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
if docker ps -a | grep -q "nr_node_mysql"; then
|
|
19
|
-
docker start nr_node_mysql;
|
|
20
|
-
else
|
|
21
|
-
docker run -d --name nr_node_mysql \
|
|
22
|
-
-e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" \
|
|
23
|
-
-e "MYSQL_ROOT_PASSWORD=" \
|
|
24
|
-
-p 3306:3306 mysql:5;
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
if docker ps -a | grep -q "nr_node_redis"; then
|
|
28
|
-
docker start nr_node_redis;
|
|
29
|
-
else
|
|
30
|
-
docker run -d --name nr_node_redis -p 6379:6379 redis;
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
if docker ps -a | grep -q "nr_node_cassandra"; then
|
|
34
|
-
docker start nr_node_cassandra;
|
|
35
|
-
else
|
|
36
|
-
docker run -d --name nr_node_cassandra -p 9042:9042 zmarcantel/cassandra;
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
if docker ps -a | grep -q "nr_node_postgres"; then
|
|
40
|
-
docker start nr_node_postgres;
|
|
41
|
-
else
|
|
42
|
-
docker run -d --name nr_node_postgres -p 5432:5432 postgres:9.2;
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
if docker ps -a | grep -q "nr_node_rabbit"; then
|
|
46
|
-
docker start nr_node_rabbit;
|
|
47
|
-
else
|
|
48
|
-
docker run -d --name nr_node_rabbit -p 5672:5672 rabbitmq:3;
|
|
49
|
-
fi
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const Github = require('./github')
|
|
5
|
-
|
|
6
|
-
const FILE_NAME = 'NEWS.md'
|
|
7
|
-
const PROPOSED_NOTES_HEADER = 'Proposed Release Notes'
|
|
8
|
-
const NEXT_VERSION_HEADER = '### vNext (TBD):'
|
|
9
|
-
|
|
10
|
-
async function generateReleaseNotes() {
|
|
11
|
-
try {
|
|
12
|
-
const github = new Github()
|
|
13
|
-
const latestRelease = await github.getLatestRelease()
|
|
14
|
-
console.log(`The latest release is: ${latestRelease.name} published: ${latestRelease.published_at}`)
|
|
15
|
-
console.log(`Tag: ${latestRelease.tag_name}, Target: ${latestRelease.target_commitish}`)
|
|
16
|
-
|
|
17
|
-
const tag = await github.getTagByName(latestRelease.tag_name)
|
|
18
|
-
console.log('The tag commit sha is: ', tag.commit.sha)
|
|
19
|
-
|
|
20
|
-
const commit = await github.getCommit(tag.commit.sha)
|
|
21
|
-
const commitDate = commit.commit.committer.date
|
|
22
|
-
|
|
23
|
-
console.log(`Finding merged pull requests since: ${commitDate}`)
|
|
24
|
-
|
|
25
|
-
const mergedPullRequests = await github.getMergedPullRequestsSince(commitDate)
|
|
26
|
-
console.log(`Found ${mergedPullRequests.length}`)
|
|
27
|
-
|
|
28
|
-
const releaseNoteData = mergedPullRequests.map((pr) => {
|
|
29
|
-
const parts = pr.body.split(/(?:^|\n)##\s*/g)
|
|
30
|
-
|
|
31
|
-
// If only has one part, not in appropriate format.
|
|
32
|
-
if (parts.length === 1) {
|
|
33
|
-
return {
|
|
34
|
-
notes: generateUnformattedNotes(pr.body),
|
|
35
|
-
url: pr.html_url
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const {1: proposedReleaseNotes} = parts
|
|
40
|
-
|
|
41
|
-
const titleRemoved = proposedReleaseNotes.replace(PROPOSED_NOTES_HEADER, '')
|
|
42
|
-
return {
|
|
43
|
-
notes: titleRemoved,
|
|
44
|
-
url: pr.html_url
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
const finalData = releaseNoteData.reduce((result, currentValue) => {
|
|
49
|
-
result.notes += '\n\n' + currentValue.notes.trim()
|
|
50
|
-
result.links += `\n\n* PR: ${currentValue.url}\n`
|
|
51
|
-
return result
|
|
52
|
-
}, {
|
|
53
|
-
notes: '',
|
|
54
|
-
links: ''
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
console.log('Final data: ', JSON.stringify(finalData))
|
|
58
|
-
|
|
59
|
-
await updateReleaseNotes(FILE_NAME, finalData.notes)
|
|
60
|
-
|
|
61
|
-
console.log('*** [SUCCESS] ***')
|
|
62
|
-
} catch(err) {
|
|
63
|
-
console.log('! [FAILURE] !')
|
|
64
|
-
console.error(err)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function generateUnformattedNotes(originalNotes) {
|
|
69
|
-
let unformattedNotes = originalNotes
|
|
70
|
-
|
|
71
|
-
// Drop extra snyk details and just keep high-level summary.
|
|
72
|
-
if (originalNotes.indexOf('snyk:metadata') >= 0) {
|
|
73
|
-
const snykParts = originalNotes.split('<details>')
|
|
74
|
-
const {0: snykDescription} = snykParts
|
|
75
|
-
|
|
76
|
-
unformattedNotes = snykDescription.trim()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const needsReviewNotes = [
|
|
80
|
-
'--- NOTES NEEDS REVIEW ---',
|
|
81
|
-
unformattedNotes,
|
|
82
|
-
'--------------------------'
|
|
83
|
-
].join('\n')
|
|
84
|
-
|
|
85
|
-
return needsReviewNotes
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function updateReleaseNotes(file, newNotes) {
|
|
89
|
-
const promise = new Promise((resolve, reject) => {
|
|
90
|
-
fs.readFile(file, 'utf8', function (err, data) {
|
|
91
|
-
if (err) {
|
|
92
|
-
return reject(err)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (data.startsWith(NEXT_VERSION_HEADER)) {
|
|
96
|
-
const errMessage = [
|
|
97
|
-
`${file} already contains '${NEXT_VERSION_HEADER}'`,
|
|
98
|
-
'Delete existing vNext release notes (if desired) and run again'
|
|
99
|
-
].join('\n')
|
|
100
|
-
|
|
101
|
-
return reject(new Error(errMessage))
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const newContent = [
|
|
105
|
-
NEXT_VERSION_HEADER,
|
|
106
|
-
newNotes,
|
|
107
|
-
'\n\n',
|
|
108
|
-
data
|
|
109
|
-
].join('')
|
|
110
|
-
|
|
111
|
-
fs.writeFile(file, newContent, 'utf8', function (err) {
|
|
112
|
-
if (err) {
|
|
113
|
-
return reject(err)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
console.log(`Added new release notes to ${file} under the ${NEXT_VERSION_HEADER}`)
|
|
117
|
-
|
|
118
|
-
resolve()
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
return promise
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
generateReleaseNotes()
|
package/bin/github.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Octokit } = require("@octokit/rest")
|
|
4
|
-
|
|
5
|
-
if (!process.env.GITHUB_TOKEN) {
|
|
6
|
-
console.log('GITHUB_TOKEN recommended to be set in ENV')
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const octokit = new Octokit({
|
|
10
|
-
auth: process.env.GITHUB_TOKEN,
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
class Github {
|
|
14
|
-
constructor(repoOwner, repository) {
|
|
15
|
-
// Default to node agent repo for now
|
|
16
|
-
this.repoOwner = repoOwner || 'newrelic'
|
|
17
|
-
this.repository = repository || 'node-newrelic'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async getLatestRelease() {
|
|
21
|
-
const result = await octokit.repos.getLatestRelease({
|
|
22
|
-
owner: this.repoOwner,
|
|
23
|
-
repo: this.repository
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
return result.data
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async getTagByName(name) {
|
|
30
|
-
const perPage = 100
|
|
31
|
-
|
|
32
|
-
let pageNum = 1
|
|
33
|
-
|
|
34
|
-
let result = null
|
|
35
|
-
do {
|
|
36
|
-
result = await octokit.repos.listTags({
|
|
37
|
-
owner: this.repoOwner,
|
|
38
|
-
repo: this.repository,
|
|
39
|
-
per_page: perPage,
|
|
40
|
-
page: pageNum
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
const found = result.data.find((tag) => {
|
|
44
|
-
return tag.name === name
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
if (found) {
|
|
48
|
-
return found
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
pageNum++
|
|
52
|
-
} while (result.data.length === perPage) // there *might* be more data
|
|
53
|
-
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getCommit(sha) {
|
|
58
|
-
const result = await octokit.repos.getCommit({
|
|
59
|
-
owner: this.repoOwner,
|
|
60
|
-
repo: this.repository,
|
|
61
|
-
ref: sha
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
return result.data
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async getMergedPullRequestsSince(date) {
|
|
68
|
-
const perPage = 50
|
|
69
|
-
|
|
70
|
-
const comparisonDate = new Date(date)
|
|
71
|
-
|
|
72
|
-
let pageNum = 1
|
|
73
|
-
const mergedPullRequests = []
|
|
74
|
-
let result = null
|
|
75
|
-
let hadData = false
|
|
76
|
-
|
|
77
|
-
do {
|
|
78
|
-
result = await octokit.pulls.list({
|
|
79
|
-
owner: this.repoOwner,
|
|
80
|
-
repo: this.repository,
|
|
81
|
-
state: 'closed',
|
|
82
|
-
sort: 'updated',
|
|
83
|
-
direction: 'desc',
|
|
84
|
-
per_page: perPage,
|
|
85
|
-
page: pageNum
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
const mergedPrs = result.data.filter((pr) => {
|
|
89
|
-
return pr.merged_at && new Date(pr.merged_at) > comparisonDate
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
mergedPullRequests.push(...mergedPrs)
|
|
93
|
-
// Since we are going by 'updated' on query but merged on filter,
|
|
94
|
-
// there's a chance some boundaries are off. While in super extreme
|
|
95
|
-
// cases we could still miss some it is unlikely given we are grabbing
|
|
96
|
-
// large pages.
|
|
97
|
-
hadData = mergedPrs.length > 0
|
|
98
|
-
|
|
99
|
-
pageNum++
|
|
100
|
-
} while (result.data.length === perPage && hadData) // might be more in next batch
|
|
101
|
-
|
|
102
|
-
return mergedPullRequests
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async getLatestWorkflowRun(nameOrId, branch) {
|
|
106
|
-
// Appears to return in latest order.
|
|
107
|
-
const runs = await octokit.actions.listWorkflowRuns({
|
|
108
|
-
owner: this.repoOwner,
|
|
109
|
-
repo: this.repository,
|
|
110
|
-
workflow_id: nameOrId,
|
|
111
|
-
branch: branch,
|
|
112
|
-
per_page: 5
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
return runs.data.workflow_runs[0]
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
module.exports = Github
|
package/bin/publish-docs.sh
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#! /bin/sh
|
|
2
|
-
|
|
3
|
-
# Copyright 2020 New Relic Corporation. All rights reserved.
|
|
4
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
|
|
6
|
-
PACKAGE_VERSION=$(node -e 'console.log(require("./package").version)')
|
|
7
|
-
|
|
8
|
-
git checkout gh-pages
|
|
9
|
-
git pull origin gh-pages
|
|
10
|
-
git merge -
|
|
11
|
-
npm run public-docs
|
|
12
|
-
git rm -r docs
|
|
13
|
-
mv out docs
|
|
14
|
-
git add docs
|
|
15
|
-
git commit -m "docs: update for ${PACKAGE_VERSION}"
|
|
16
|
-
git push origin gh-pages && git push public gh-pages:gh-pages
|