Skip to content

Commit be33b0e

Browse files
authored
feat: Publish info file (safe-global#1179)
1 parent c7f360b commit be33b0e

File tree

9 files changed

+161
-6
lines changed

9 files changed

+161
-6
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Create publish info file
2+
3+
on:
4+
release:
5+
types: [created]
6+
workflow_dispatch:
7+
push:
8+
branches:
9+
- prepare-release
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
generate-publish-info:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
- name: Use Node.js ${{ matrix.node-version }}
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
cache: yarn
24+
- run: |
25+
yarn install --frozen-lockfile
26+
yarn build
27+
28+
- name: Run integrity check script
29+
run: |
30+
yarn generate-publish-info
31+
32+
- name: Upload YAML artifact
33+
uses: actions/upload-artifact@v4
34+
with:
35+
name: publish-info
36+
path: ./publish-info
37+
38+
- name: Show YAML output
39+
run: cat ./publish-info/*.yml

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,5 @@ openapi/
6565
yalc.lock
6666
# Local Netlify folder
6767
.netlify
68+
69+
publish-info/

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"test": "FORCE_COLOR=1 lerna run test --stream",
1010
"play": "ts-node ./playground/config/run.ts",
1111
"format": "lerna run format && prettier --write \"playground/**/*.ts\"",
12-
"prepare": "husky"
12+
"prepare": "husky",
13+
"generate-publish-info": "ts-node ./scripts/generate-publish-info.ts"
1314
},
1415
"workspaces": {
1516
"packages": [

packages/protocol-kit/tsconfig.build.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"declaration": true,
55
"emitDeclarationOnly": true,
66
"declarationMap": true,
7-
"composite": true,
87
"outDir": "dist"
98
},
109
"include": ["src/**/*", "test-utils/**/*"],

packages/protocol-kit/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"paths": {
66
"@safe-global/protocol-kit/*": ["./src/*"]
77
},
8-
"composite": true,
98
"outDir": "dist"
109
},
1110
"include": ["src/**/*", "tests/**/*"],

packages/relay-kit/tsconfig.build.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"declaration": true,
55
"emitDeclarationOnly": true,
66
"declarationMap": true,
7-
"composite": true,
87
"outDir": "dist"
98
},
109
"include": ["src/**/*", "test-utils/**/*"],

packages/relay-kit/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"paths": {
66
"@safe-global/relay-kit/*": ["./src/*"]
77
},
8-
"composite": true,
98
"outDir": "dist"
109
},
1110
"include": ["src/**/*"],

playground/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"extends": "../tsconfig.settings.json",
33
"compilerOptions": {
4-
"composite": true,
54
"noImplicitThis": false,
65
"outDir": "dist"
76
},

scripts/generate-publish-info.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { execFile } from 'child_process'
2+
import * as fs from 'fs'
3+
import * as path from 'path'
4+
import * as yaml from 'yaml'
5+
6+
type PackagePublishInfo = {
7+
id: string
8+
name: string
9+
version: string
10+
size: number
11+
unpackedSize: number
12+
shasum: string
13+
integrity: string
14+
filename: string
15+
entryCount: number
16+
}
17+
18+
type NpmPublishOutput = Record<
19+
string,
20+
PackagePublishInfo & {
21+
files?: string[]
22+
bundled?: unknown[]
23+
}
24+
>
25+
26+
const executeCommand = (command: string, args: string[]): Promise<string> => {
27+
return new Promise((resolve, reject) => {
28+
execFile(command, args, (error, stdout, stderr) => {
29+
if (error) {
30+
return reject(`Error executing command: ${error.message}`)
31+
}
32+
33+
if (stderr) {
34+
console.warn(`Warning during execution: ${stderr}`)
35+
}
36+
37+
resolve(stdout)
38+
})
39+
})
40+
}
41+
42+
const writeToFile = (filePath: string, data: string): Promise<void> => {
43+
return new Promise((resolve, reject) => {
44+
const safeDir = path.join(process.cwd(), 'publish-info')
45+
46+
fs.mkdir(safeDir, { recursive: true, mode: 0o700 }, (err) => {
47+
if (err) return reject(`Directory creation failed: ${err.message}`)
48+
49+
const fullPath = path.join(safeDir, path.basename(filePath))
50+
51+
fs.writeFile(fullPath, data, { mode: 0o600 }, (writeErr) => {
52+
if (writeErr) return reject(`File write failed: ${writeErr.message}`)
53+
resolve()
54+
})
55+
})
56+
})
57+
}
58+
59+
const sanitizePublishOutput = (jsonData: NpmPublishOutput): Record<string, PackagePublishInfo> => {
60+
return Object.fromEntries(
61+
Object.entries(jsonData).map(([pkgName, pkgData]) => {
62+
const { files, bundled, ...cleanData } = pkgData
63+
64+
return [pkgName, cleanData]
65+
})
66+
)
67+
}
68+
69+
const getReadableFilename = (): string => {
70+
try {
71+
const now = new Date()
72+
const pad = (n: number) => n.toString().padStart(2, '0')
73+
const datePart = [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join('-')
74+
const timePart = [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join('-')
75+
const timestamp = `${datePart}_${timePart}`
76+
77+
return `publish-info_${timestamp}.yml`
78+
} catch {
79+
return `publish-info_${Date.now()}.yml`
80+
}
81+
}
82+
83+
const main = async () => {
84+
try {
85+
const projectRoot = path.join(__dirname, '../')
86+
process.chdir(projectRoot)
87+
88+
const stdout = await executeCommand('npm', [
89+
'publish',
90+
'--access',
91+
'public',
92+
'--dry-run',
93+
'--workspaces',
94+
'--json',
95+
'--ignore-scripts'
96+
])
97+
98+
let jsonOutput: NpmPublishOutput
99+
try {
100+
jsonOutput = JSON.parse(stdout) as NpmPublishOutput
101+
} catch (parseError) {
102+
throw new Error(`Error parsing JSON output: ${(parseError as Error).message}`)
103+
}
104+
105+
const cleanedOutput = sanitizePublishOutput(jsonOutput)
106+
const yamlOutput = yaml.stringify(cleanedOutput)
107+
108+
const outputFileName = getReadableFilename()
109+
await writeToFile(outputFileName, yamlOutput)
110+
111+
console.log(`Output stored in ${outputFileName}`)
112+
} catch (error) {
113+
console.error(`Error: ${error instanceof Error ? error.message : error}`)
114+
process.exit(1)
115+
}
116+
}
117+
118+
main()

0 commit comments

Comments
 (0)