File size: 7,718 Bytes
6582e08 | 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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | /*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
//
// Creates an artifact that can be given to users for testing alpha/beta builds:
//
// aws-toolkit-vscode-99.0.0-gxxxxxxx.vsix
// or amazon-q-vscode-99.0.0-gxxxxxxx.vsix
//
// Where `xxxxxxx` is the first 7 characters of the commit hash that produced the artifact.
//
// The script works like this:
// 1. temporarily change `version` in package.json
// 2. invoke `vsce package`
// 3. restore the original package.json
//
import * as child_process from 'child_process' // eslint-disable-line no-restricted-imports
import * as nodefs from 'fs' // eslint-disable-line no-restricted-imports
import * as path from 'path'
import { downloadLanguageServer } from './lspArtifact'
function parseArgs() {
// Invoking this script with argument "foo":
// $ npm run package -- foo
// yields this argv:
// 0: /…/node_modules/.bin/ts-node
// 1: /…/src/scripts/build/package.ts
// 2: foo
const args: { [key: string]: any } = {
/** Produce an unoptimized VSIX. Include git SHA in version string. */
debug: false,
/** Skips `npm run clean` when building the VSIX. This prevents file watching from breaking. */
skipClean: false,
feature: '',
}
const givenArgs = process.argv.slice(2)
const validOptions = ['--debug', '--no-clean', '--feature']
const expectValue = ['--feature']
for (let i = 0; i < givenArgs.length; i++) {
const a = givenArgs[i]
const argName = a.replace(/^-+/, '') // "--foo" => "foo"
if (!validOptions.includes(a)) {
throw Error(`invalid argument: ${a}`)
}
if (expectValue.includes(a)) {
i++
const val = givenArgs[i]
if (val === undefined) {
throw Error(`missing value for arg: ${a}`)
}
args[argName] = val
} else {
args[argName] = true
}
}
return args
}
/**
* If the _current_ commit is tagged as a release ("v1.26.0") then it is a "release build", else it
* is a prerelease/nightly/edge/preview build.
*/
function isRelease(): boolean {
const tag = child_process.execFileSync('git', ['tag', '-l', '--contains', 'HEAD']).toString()
return !!tag?.match(/v\d+\.\d+\.\d+/)
}
/**
* Whether or not this a private beta build
*/
function isBeta(): boolean {
try {
// This path only exists for packages/toolkit.
// As noted before: "Importing from `src` isn't great but it does make things simple"
// TODO: Generalize betaUrl for all packages.
const betaUrl = require(path.resolve('./src/dev/config')).betaUrl
return !!betaUrl
} catch {
return false
}
}
/**
* Gets a suffix to append to the version-string, or empty for release builds.
*
* TODO: use `git describe` instead.
*
* @returns version-string suffix, for example: "-e6ecd84685a9"
*/
function getVersionSuffix(feature: string, debug: boolean): string {
if (isRelease()) {
return ''
}
const debugSuffix = debug ? '-debug' : ''
const featureSuffix = feature === '' ? '' : `-${feature}`
const commitId = child_process.execFileSync('git', ['rev-parse', '--short=7', 'HEAD']).toString().trim()
// Commit id is prefixed with "g" because "-0abc123" is not a valid semver prerelease, and will cause vsce to fail.
const commitSuffix = commitId ? `-g${commitId}` : ''
return `${debugSuffix}${featureSuffix}${commitSuffix}`
}
async function main() {
const args = parseArgs()
// It is expected that this will package from a packages/{subproject} folder.
// There is a base config in packages/
const packageJsonFile = './package.json'
const backupJsonFile = `${packageJsonFile}.package.bk`
const webpackConfigJsFile = '../webpack.base.config.js'
const backupWebpackConfigFile = `${webpackConfigJsFile}.package.bk`
if (!nodefs.existsSync(packageJsonFile)) {
throw new Error(`package.json not found, cannot package this directory: ${process.cwd()}`)
}
let release = true
try {
release = isRelease()
if (release && isBeta()) {
throw new Error('Cannot package VSIX as both a release and a beta simultaneously')
}
// Create backup file so we can restore the originals later.
nodefs.copyFileSync(packageJsonFile, backupJsonFile)
const packageJson = JSON.parse(nodefs.readFileSync(packageJsonFile, { encoding: 'utf-8' }))
if (!release || args.debug) {
const versionSuffix = getVersionSuffix(args.feature, args.debug)
const version = packageJson.version
if (isBeta()) {
// Declare an arbitrarily high version number, to stop VSC from auto-updating "beta" builds.
packageJson.version = `99.0.0${versionSuffix}`
} else {
packageJson.version = version.replace('-SNAPSHOT', versionSuffix)
}
if (args.skipClean) {
// Clearly we need `prepublish` to be a standalone script and not a bunch of `npm` commands
const prepublish = packageJson.scripts['vscode:prepublish']
const replaced = prepublish.replace('npm run clean', 'echo "Skipped clean"')
packageJson.scripts['vscode:prepublish'] = replaced
}
if (args.debug) {
nodefs.copyFileSync(webpackConfigJsFile, backupWebpackConfigFile)
const webpackConfigJs = nodefs.readFileSync(webpackConfigJsFile, { encoding: 'utf-8' })
nodefs.writeFileSync(webpackConfigJsFile, webpackConfigJs.replace(/minimize: true/, 'minimize: false'))
}
}
nodefs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, undefined, ' '))
// add language server bundle
if (packageJson.name === 'amazon-q-vscode') {
await downloadLanguageServer()
}
child_process.execFileSync(
'vsce',
[
'package',
'--ignoreFile',
'../.vscodeignore.packages',
/**
* Depdendency gathering not required because we bundle with webpack: https://github.com/microsoft/vscode-vsce/issues/439
*
* Removing this arg will cause packaging to break due to issues in src.gen/.../node_modules,
* since those dependencies are disjoint (i.e. not a workspace in the root package.json)
*/
'--no-dependencies',
],
{
stdio: 'inherit',
shell: process.platform === 'win32', // For vsce.cmd on Windows.
}
)
console.log(`VSIX Version: ${packageJson.version}`)
// Hoist .vsix to root folder, because the release infra expects it to be there.
// TODO: Once we can support releasing multiple artifacts,
// let's just keep the .vsix in its respective project folder in packages/
const vsixName = `${packageJson.name}-${packageJson.version}.vsix`
nodefs.renameSync(vsixName, `../../${vsixName}`)
} catch (e) {
console.log(e)
throw Error('package.ts: failed')
} finally {
// Restore the original files.
nodefs.copyFileSync(backupJsonFile, packageJsonFile)
nodefs.unlinkSync(backupJsonFile)
if (args.debug) {
nodefs.copyFileSync(backupWebpackConfigFile, webpackConfigJsFile)
nodefs.unlinkSync(backupWebpackConfigFile)
}
}
}
main()
|