1+ /*
2+ * Copyright The OpenTelemetry Authors
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * https://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ /**
18+ * Replacement for: lerna publish from-package --no-push --no-private --no-git-tag-version --no-verify-access --yes
19+ * Ref: https://github.com/lerna/lerna/tree/main/commands/publish#bump-from-package
20+ *
21+ * Usage: node ./scripts/publish-to-npm.mjs
22+ *
23+ * - [X] checks package versions directly from the `pacakge.json` files (from-package)
24+ * - [X] filters out all private repos (--no-private)
25+ * - [X] does not create tags o push anything (--no-push & --no-git-tag-version)
26+ * - [X] does not any extra request to verify access tokens (--no-verify-access)
27+ * - [X] does not ask for confirmation (--yes)
28+ */
29+
30+ import { exec } from 'child_process' ;
31+ import path from 'path' ;
32+ import { readFileSync } from 'fs' ;
33+ import { globSync } from 'glob' ;
34+
35+ const readJson = ( filePath ) => {
36+ return JSON . parse ( readFileSync ( filePath ) ) ;
37+ } ;
38+ const execCommand = ( cmd , options = { } ) => {
39+ return new Promise ( ( res , rej ) => {
40+ exec ( cmd , options , ( err , stdout , stderr ) => {
41+ if ( err ) {
42+ rej ( stderr ) ;
43+ } else {
44+ res ( stdout ) ;
45+ }
46+ } ) ;
47+ } ) ;
48+ } ;
49+
50+ // Check data from packages (former lerna --from-package option)
51+ const getPackages = ( ) => {
52+ const TOP = process . cwd ( ) ;
53+ const pj = readJson ( path . join ( TOP , 'package.json' ) ) ;
54+ return pj . workspaces
55+ . map ( ( wsGlob ) => globSync ( path . join ( wsGlob , 'package.json' ) ) )
56+ . flat ( )
57+ . map ( ( p ) => {
58+ const pkgInfo = readJson ( p ) ;
59+ pkgInfo . location = path . dirname ( p ) ;
60+ return pkgInfo ;
61+ } ) ;
62+ }
63+ const publicPkgList = getPackages ( ) . filter ( pkg => ! pkg . private ) ;
64+ const publicPkgVersions = await Promise . all ( publicPkgList . map ( async ( pkg ) => {
65+ const infoText = await execCommand ( `npm info ${ pkg . name } --json time` ) ;
66+ return JSON . parse ( infoText ) ;
67+ } ) ) ;
68+
69+ const publishTasks = [ ] ;
70+ publicPkgList . forEach ( ( pkg , idx ) => {
71+ const versions = new Set ( Object . keys ( publicPkgVersions [ idx ] ) ) ;
72+
73+ // Add tasks if no version matches the current
74+ if ( ! versions . has ( pkg . version ) ) {
75+ publishTasks . push ( { cmd : 'npm publish' , opts : { cwd : pkg . location } } ) ;
76+ }
77+ } ) ;
78+
79+ // For better logging we may want to publish packages sequentially
80+ for ( const task of publishTasks ) {
81+ console . log ( `Publishing package ${ pkg . name } with version ${ pkg . version } ` ) ;
82+ await execCommand ( task . cmd , task . opts ) ;
83+ }
0 commit comments