-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathcode-push.config.ts
More file actions
145 lines (130 loc) · 4.32 KB
/
code-push.config.ts
File metadata and controls
145 lines (130 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* CodePush CLI config for publishing OTA updates.
* Implement bundleUploader, getReleaseHistory, and setReleaseHistory to use
* your storage (e.g. S3, GCS, or a custom API). See OTA_UPDATES.md.
*/
import { execFileSync } from 'child_process'
import * as fs from 'fs'
import * as os from 'os'
import * as path from 'path'
import { fileURLToPath } from 'url'
import type {
CliConfigInterface,
ReleaseHistoryInterface
} from '@bravemobile/react-native-code-push'
// ESM (how ts-node / code-push load this file in CI): __dirname is undefined; use import.meta.url.
const packageDir = path.dirname(fileURLToPath(import.meta.url))
const OTA_OUTPUT_DIR = path.join(packageDir, 'build', 'codepush')
const DEFAULT_S3_PREFIX = 'mobile-ota'
const getRequiredEnv = (key: string) => {
const value = process.env[key]
if (!value) {
throw new Error(`Missing required env var: ${key}`)
}
return value
}
const getBaseUrl = () => {
return (
process.env.OTA_PUBLIC_BASE_URL?.replace(/\/$/, '') ??
`https://download.audius.co/${DEFAULT_S3_PREFIX}`
)
}
const getS3Path = (...parts: string[]) => {
const bucket = getRequiredEnv('OTA_S3_BUCKET')
const prefix = (process.env.OTA_S3_PREFIX ?? DEFAULT_S3_PREFIX).replace(/^\/|\/$/g, '')
return `s3://${bucket}/${prefix}/${parts.join('/')}`
}
const uploadFileToS3 = (sourcePath: string, destinationPath: string, cacheControl: string) => {
execFileSync(
'aws',
[
's3',
'cp',
sourcePath,
destinationPath,
'--content-type',
'application/json',
'--cache-control',
cacheControl
],
{ stdio: 'inherit' }
)
}
const Config: CliConfigInterface = {
async bundleUploader(
source: string,
platform: 'ios' | 'android',
identifier: string | undefined
): Promise<{ downloadUrl: string }> {
const id = identifier ?? 'production'
const fileName = path.basename(source)
const objectKey = `bundles/${platform}/${id}/${Date.now()}-${fileName}`
const destinationPath = getS3Path(objectKey)
execFileSync('aws', ['s3', 'cp', source, destinationPath, '--cache-control', 'public,max-age=31536000,immutable'], {
stdio: 'inherit'
})
return {
downloadUrl: `${getBaseUrl()}/${objectKey}`
}
},
async getReleaseHistory(
targetBinaryVersion: string,
platform: 'ios' | 'android',
identifier: string | undefined
): Promise<ReleaseHistoryInterface> {
const id = identifier ?? 'production'
const url = `${getBaseUrl()}/histories/${platform}/${id}/${targetBinaryVersion}.json`
try {
const res = await fetch(url)
if (!res.ok) {
return {}
}
const data = (await res.json()) as ReleaseHistoryInterface
return data
} catch {
const filePath = path.join(
OTA_OUTPUT_DIR,
'histories',
platform,
id,
`${targetBinaryVersion}.json`
)
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as ReleaseHistoryInterface
return data
}
return {}
}
},
async setReleaseHistory(
targetBinaryVersion: string,
jsonFilePath: string,
releaseInfo: ReleaseHistoryInterface,
platform: 'ios' | 'android',
identifier: string | undefined
): Promise<void> {
const id = identifier ?? 'production'
const dir = path.join(OTA_OUTPUT_DIR, 'histories', platform, id)
fs.mkdirSync(dir, { recursive: true })
const outPath = path.join(dir, `${targetBinaryVersion}.json`)
fs.writeFileSync(outPath, JSON.stringify(releaseInfo, null, 2))
const tmpJsonPath = path.join(
os.tmpdir(),
`codepush-history-${platform}-${id}-${targetBinaryVersion}.json`
)
fs.writeFileSync(tmpJsonPath, JSON.stringify(releaseInfo, null, 2))
const destinationPath = getS3Path(
'histories',
platform,
id,
`${targetBinaryVersion}.json`
)
uploadFileToS3(tmpJsonPath, destinationPath, 'no-store, no-cache, must-revalidate')
}
}
// CommonJS `require()` (used by the code-push CLI) only attaches named exports to `module.exports`.
// A default export ends up as `.default`, so `config.setReleaseHistory` would be undefined without these.
export const bundleUploader = Config.bundleUploader
export const getReleaseHistory = Config.getReleaseHistory
export const setReleaseHistory = Config.setReleaseHistory
export default Config