|
1 | 1 | // @ts-check
|
2 | 2 |
|
| 3 | +const { exit } = require('node:process'); |
| 4 | + |
3 | 5 | (async () => {
|
4 | 6 | const os = require('node:os');
|
5 | 7 | const path = require('node:path');
|
6 | 8 | const { mkdirSync, promises: fs, rmSync } = require('node:fs');
|
7 | 9 | const { exec } = require('./utils');
|
8 | 10 | const glob = require('glob');
|
9 |
| - const { SemVer, gte, valid: validSemVer } = require('semver'); |
| 11 | + const { SemVer, gte, valid: validSemVer, gt } = require('semver'); |
10 | 12 | // Use a node-protoc fork until apple arm32 is supported
|
11 | 13 | // https://github.com/YePpHa/node-protoc/pull/10
|
12 | 14 | const protoc = path.dirname(require('@pingghost/protoc/protoc'));
|
13 |
| - const repository = await fs.mkdtemp(path.join(os.tmpdir(), 'arduino-cli-')); |
14 | 15 |
|
15 | 16 | const { owner, repo, commitish } = (() => {
|
16 | 17 | const pkg = require(path.join(__dirname, '..', 'package.json'));
|
|
57 | 58 | return { owner, repo, commitish };
|
58 | 59 | })();
|
59 | 60 |
|
60 |
| - const url = `https://github.com/${owner}/${repo}.git`; |
61 |
| - console.log(`>>> Cloning repository from '${url}'...`); |
62 |
| - exec('git', ['clone', url, repository], { logStdout: true }); |
63 |
| - console.log(`<<< Repository cloned.`); |
64 |
| - |
65 | 61 | const { platform } = process;
|
66 | 62 | const resourcesFolder = path.join(
|
67 | 63 | __dirname,
|
|
87 | 83 | // - `git-snapshot` for local build executed via `task build`. We do not do this.
|
88 | 84 | // - rest, we assume it is a valid semver and has the corresponding tagged code, we use the tag to generate the APIs from the `proto` files.
|
89 | 85 | /*
|
90 |
| - { |
91 |
| - "Application": "arduino-cli", |
92 |
| - "VersionString": "nightly-20210126", |
93 |
| - "Commit": "079bb6c6", |
94 |
| - "Status": "alpha", |
95 |
| - "Date": "2021-01-26T01:46:31Z" |
96 |
| - } |
97 |
| - */ |
| 86 | + { |
| 87 | + "Application": "arduino-cli", |
| 88 | + "VersionString": "nightly-20210126", |
| 89 | + "Commit": "079bb6c6", |
| 90 | + "Status": "alpha", |
| 91 | + "Date": "2021-01-26T01:46:31Z" |
| 92 | + } |
| 93 | + */ |
98 | 94 | const versionObject = JSON.parse(versionJson);
|
99 |
| - let version = versionObject.VersionString; |
100 |
| - if (validSemVer(version)) { |
101 |
| - // https://github.com/arduino/arduino-cli/pull/2374 |
102 |
| - if (gte(new SemVer(version, { loose: true }), new SemVer('0.35.0-rc.1'))) { |
103 |
| - version = `v${version}`; |
| 95 | + const version = versionObject.VersionString; |
| 96 | + |
| 97 | + // Clone the repository and check out the tagged version |
| 98 | + // Return folder with proto files |
| 99 | + async function getProtoPath(forceCliVersion) { |
| 100 | + const repository = await fs.mkdtemp(path.join(os.tmpdir(), 'arduino-cli-')); |
| 101 | + |
| 102 | + const url = `https://github.com/${owner}/${repo}.git`; |
| 103 | + console.log(`>>> Cloning repository from '${url}'...`); |
| 104 | + exec('git', ['clone', url, repository], { logStdout: true }); |
| 105 | + console.log(`<<< Repository cloned.`); |
| 106 | + |
| 107 | + let cliVersion = forceCliVersion || version; |
| 108 | + if (validSemVer(cliVersion)) { |
| 109 | + // https://github.com/arduino/arduino-cli/pull/2374 |
| 110 | + if ( |
| 111 | + gte(new SemVer(version, { loose: true }), new SemVer('0.35.0-rc.1')) |
| 112 | + ) { |
| 113 | + cliVersion = `v${cliVersion}`; |
| 114 | + } |
| 115 | + console.log(`>>> Checking out tagged version: '${cliVersion}'...`); |
| 116 | + exec('git', ['-C', repository, 'fetch', '--all', '--tags'], { |
| 117 | + logStdout: true, |
| 118 | + }); |
| 119 | + exec( |
| 120 | + 'git', |
| 121 | + ['-C', repository, 'checkout', `tags/${cliVersion}`, '-b', cliVersion], |
| 122 | + { logStdout: true } |
| 123 | + ); |
| 124 | + console.log(`<<< Checked out tagged version: '${cliVersion}'.`); |
| 125 | + } else if (forceCliVersion) { |
| 126 | + console.log(`WARN: invalid semver: '${forceCliVersion}'.`); |
| 127 | + // If the forced version is invalid, do not proceed with fallbacks. |
| 128 | + return undefined; |
| 129 | + } else if (commitish) { |
| 130 | + console.log( |
| 131 | + `>>> Checking out commitish from 'package.json': '${commitish}'...` |
| 132 | + ); |
| 133 | + exec('git', ['-C', repository, 'checkout', commitish], { |
| 134 | + logStdout: true, |
| 135 | + }); |
| 136 | + console.log( |
| 137 | + `<<< Checked out commitish from 'package.json': '${commitish}'.` |
| 138 | + ); |
| 139 | + } else if (versionObject.Commit) { |
| 140 | + console.log( |
| 141 | + `>>> Checking out commitish from the CLI: '${versionObject.Commit}'...` |
| 142 | + ); |
| 143 | + exec('git', ['-C', repository, 'checkout', versionObject.Commit], { |
| 144 | + logStdout: true, |
| 145 | + }); |
| 146 | + console.log( |
| 147 | + `<<< Checked out commitish from the CLI: '${versionObject.Commit}'.` |
| 148 | + ); |
| 149 | + } else { |
| 150 | + console.log( |
| 151 | + `WARN: no 'git checkout'. Generating from the HEAD revision.` |
| 152 | + ); |
104 | 153 | }
|
105 |
| - console.log(`>>> Checking out tagged version: '${version}'...`); |
106 |
| - exec('git', ['-C', repository, 'fetch', '--all', '--tags'], { |
107 |
| - logStdout: true, |
108 |
| - }); |
109 |
| - exec( |
110 |
| - 'git', |
111 |
| - ['-C', repository, 'checkout', `tags/${version}`, '-b', version], |
112 |
| - { logStdout: true } |
113 |
| - ); |
114 |
| - console.log(`<<< Checked out tagged version: '${version}'.`); |
115 |
| - } else if (commitish) { |
116 |
| - console.log( |
117 |
| - `>>> Checking out commitish from 'package.json': '${commitish}'...` |
118 |
| - ); |
119 |
| - exec('git', ['-C', repository, 'checkout', commitish], { logStdout: true }); |
120 |
| - console.log( |
121 |
| - `<<< Checked out commitish from 'package.json': '${commitish}'.` |
122 |
| - ); |
123 |
| - } else if (versionObject.Commit) { |
124 |
| - console.log( |
125 |
| - `>>> Checking out commitish from the CLI: '${versionObject.Commit}'...` |
126 |
| - ); |
127 |
| - exec('git', ['-C', repository, 'checkout', versionObject.Commit], { |
128 |
| - logStdout: true, |
129 |
| - }); |
130 |
| - console.log( |
131 |
| - `<<< Checked out commitish from the CLI: '${versionObject.Commit}'.` |
132 |
| - ); |
133 |
| - } else { |
134 |
| - console.log(`WARN: no 'git checkout'. Generating from the HEAD revision.`); |
| 154 | + |
| 155 | + return path.join(repository, 'rpc'); |
| 156 | + } |
| 157 | + |
| 158 | + const protoPath = await getProtoPath(); |
| 159 | + |
| 160 | + if (!protoPath) { |
| 161 | + console.log(`Could not find the proto files folder.`); |
| 162 | + exit(1); |
135 | 163 | }
|
136 | 164 |
|
137 | 165 | console.log('>>> Generating TS/JS API from:');
|
138 |
| - exec('git', ['-C', repository, 'rev-parse', '--abbrev-ref', 'HEAD'], { |
| 166 | + exec('git', ['-C', protoPath, 'rev-parse', '--abbrev-ref', 'HEAD'], { |
139 | 167 | logStdout: true,
|
140 | 168 | });
|
141 | 169 |
|
142 |
| - const rpc = path.join(repository, 'rpc'); |
143 | 170 | const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol');
|
144 | 171 | // Must wipe the gen output folder. Otherwise, dangling service implementation remain in IDE2 code,
|
145 | 172 | // although it has been removed from the proto file.
|
146 | 173 | // For example, https://github.com/arduino/arduino-cli/commit/50a8bf5c3e61d5b661ccfcd6a055e82eeb510859.
|
147 | 174 | rmSync(out, { recursive: true, maxRetries: 5, force: true });
|
148 | 175 | mkdirSync(out, { recursive: true });
|
149 | 176 |
|
| 177 | + if (gt(new SemVer(version, { loose: true }), new SemVer('1.0.4'))) { |
| 178 | + // Patch for https://github.com/arduino/arduino-cli/issues/2755 |
| 179 | + // Credit https://github.com/dankeboy36/ardunno-cli-gen/pull/9/commits/64a5ac89aae605249261c8ceff7255655ecfafca |
| 180 | + // Download the 1.0.4 version and use the missing google/rpc/status.proto file. |
| 181 | + console.log('<<< Generating missing google proto files'); |
| 182 | + const v104ProtoPath = await getProtoPath('1.0.4'); |
| 183 | + if (!v104ProtoPath) { |
| 184 | + console.log(`Could not find the proto files folder for version 1.0.4.`); |
| 185 | + exit(1); |
| 186 | + } |
| 187 | + await fs.cp( |
| 188 | + path.join(v104ProtoPath, 'google'), |
| 189 | + path.join(protoPath, 'google'), |
| 190 | + { |
| 191 | + recursive: true, |
| 192 | + } |
| 193 | + ); |
| 194 | + console.log(`>>> Generated missing google file`); |
| 195 | + } |
| 196 | + |
150 | 197 | const protos = await new Promise((resolve) =>
|
151 |
| - glob('**/*.proto', { cwd: rpc }, (error, matches) => { |
| 198 | + glob('**/*.proto', { cwd: protoPath }, (error, matches) => { |
152 | 199 | if (error) {
|
153 | 200 | console.log(error.stack ?? error.message);
|
154 | 201 | resolve([]);
|
155 | 202 | return;
|
156 | 203 | }
|
157 |
| - resolve(matches.map((filename) => path.join(rpc, filename))); |
| 204 | + resolve(matches.map((filename) => path.join(protoPath, filename))); |
158 | 205 | })
|
159 | 206 | );
|
| 207 | + |
160 | 208 | if (!protos || protos.length === 0) {
|
161 |
| - console.log(`Could not find any .proto files under ${rpc}.`); |
162 |
| - process.exit(1); |
| 209 | + console.log(`Could not find any .proto files under ${protoPath}.`); |
| 210 | + exit(1); |
163 | 211 | }
|
164 | 212 |
|
165 | 213 | // Generate JS code from the `.proto` files.
|
|
169 | 217 | `--js_out=import_style=commonjs,binary:${out}`,
|
170 | 218 | `--grpc_out=generate_package_definition:${out}`,
|
171 | 219 | '-I',
|
172 |
| - rpc, |
| 220 | + protoPath, |
173 | 221 | ...protos,
|
174 | 222 | ],
|
175 | 223 | { logStdout: true }
|
|
188 | 236 | )}`,
|
189 | 237 | `--ts_out=generate_package_definition:${out}`,
|
190 | 238 | '-I',
|
191 |
| - rpc, |
| 239 | + protoPath, |
192 | 240 | ...protos,
|
193 | 241 | ],
|
194 | 242 | { logStdout: true }
|
|
0 commit comments