From a3c3b84b29e315ffba57e451ff4770b199070883 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 24 Jan 2023 20:00:48 -0800 Subject: [PATCH] feat(release): document manual release procedure Co-authored-by: Akos Kitta Co-authored-by: per1234 Signed-off-by: Akos Kitta --- docs/internal/Ubuntu.md | 1 + docs/internal/release-procedure.md | 124 +++++++++++++++++++++++++++++ package.json | 1 + scripts/merge-channel-files.js | 48 +++++++++++ scripts/update-version.js | 2 + 5 files changed, 176 insertions(+) create mode 100644 scripts/merge-channel-files.js diff --git a/docs/internal/Ubuntu.md b/docs/internal/Ubuntu.md index de556410c..9fafe36e5 100644 --- a/docs/internal/Ubuntu.md +++ b/docs/internal/Ubuntu.md @@ -16,6 +16,7 @@ sudo apt update \ libx11-dev \ libxkbfile-dev \ build-essential \ + libsecret-1-dev \ && wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash \ && source ~/.bashrc \ && nvm install 16 \ diff --git a/docs/internal/release-procedure.md b/docs/internal/release-procedure.md index 0f62d8ffa..21d9fb841 100644 --- a/docs/internal/release-procedure.md +++ b/docs/internal/release-procedure.md @@ -174,3 +174,127 @@ git push origin version- ``` replacing `` with the version you want. Then create a PR and merge it. + +## Manual build + +Creating the release for Ubuntu 18.04 ([arduino/arduino-ide#2018](https://github.com/arduino/arduino-ide/issues/2018)) and macOS M1 ([arduino/arduino-ide#408](https://github.com/arduino/arduino-ide/issues/408)) is a manual procedure. + +### Ubuntu 18.04 + - Prerequisites: + - Ask the DevOps team for an EC2 instance with at least 8 GB of RAM. + - Your account must have access to the staging environment. + - You have VPN connection to staging. + - Setup: + - To install all required dependencies, run the following script: + ```sh + sudo apt update \ + && sudo apt install --no-install-recommends --yes \ + git \ + gcc \ + curl \ + make \ + python \ + pkg-config \ + libx11-dev \ + libxkbfile-dev \ + build-essential \ + libsecret-1-dev \ + && wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash \ + && source ~/.bashrc \ + && nvm install 16 \ + && nvm use 16 \ + && nvm alias default 16 \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - \ + && echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list \ + && sudo apt update && sudo apt install --no-install-recommends yarn + ``` + - Set the environment variables to mimic a CI build: + ```sh + export IS_RELEASE=true && export CI=true + ``` + - Build: + ```sh + yarn --cwd ./electron/packager && yarn --cwd ./electron/packager package + ``` + - Artifacts: + - You have to upload the following artifacts from `./arduino-ide/electron/build/dist` to S3: + - `arduino-ide_${VERSION}_Linux_64bit.AppImage`, + - `arduino-ide_${VERSION}_Linux_64bit.zip`, and + - `stable-linux.yml` + +### macOS M1 + - Prerequisites: + - You need access to the shared Mac Mini at Toolbox. Use TeamViewer. + - You have access to the `FT Web Tooling` 1Password vault. + - Setup: + - Download the `Pro-IDE-Certificates.p12` file from `Arduino Pro IDE Apple Developer ID Certificate .p12 format` and put it somewhere on the Mac Mini. This example assumes you put the `.p12` file in the `arduino-ide` repository root, and your `cwd` is also in the `arduino-ide` repository root. + - The following environment variables must be available from the shell: + - `AC_PASSWORD`: Check `Arduino Apple developer ID App Specific Password` + - `AC_USERNAME`: Check `Arduino Apple developer ID App Specific Password` + - `AC_TEAM_ID`: "KT7ZWMCJT" + - `CSC_KEY_PASSWORD`: Check `Arduino Pro IDE Apple Developer ID certificate keychain password` + - `CSC_LINK`: `Pro-IDE-Certificates.p12` file on the Mac Mini + - `IS_RELEASE`: "true" + - `CAN_SIGN`: "true" + - `MACOS_FORCE_NOTARIZE`: "true" + + ```sh + export AC_PASSWORD="***" + export AC_USERNAME="***" + export AC_TEAM_ID="7KT7ZWMCJT" + export CSC_KEY_PASSWORD="***" + export CSC_LINK="`pwd`/Pro-IDE-Certificates.p12" + export IS_RELEASE="true" + export CAN_SIGN="true" + export MACOS_FORCE_NOTARIZE="true" + export CI="true" + ``` + + - Build: + ```sh + yarn --cwd ./electron/packager && yarn --cwd ./electron/packager package + ``` + + - Verify: + + Since you cannot drag and drop via TeamViewer, you will install the app from a command line. This example puts the IDE2 into the Desktop. Do **NOT** try to bypass the installation with a double click and open from the UI. The `node_modules` folder of the source code is implicitly in the `$PATH`, and you want to verify if the app is fully functional without the `node_modules` folder. + + ```sh + hdiutil attach ./electron/build/dist/arduino-ide_${VERSION}_macOS_ARM64.dmg \ + && cp -R /Volumes/Arduino\ IDE\ ${VERSION}-arm64/Arduino\ IDE.app ~/Desktop \ + && hdiutil unmount /Volumes/Arduino\ IDE\ ${VERSION}-arm64 \ + && codesign -dv --verbose=4 ~/Desktop/Arduino\ IDE.app \ + && ~/Desktop/Arduino\ IDE.app/Contents/MacOS/Arduino\ IDE + ``` + + - Cleanup: + - You **MUST** close the shell after the build. + - You **MUST** delete the `.p12` file and empty the trash afterward. + + - Artifacts: + - You have to upload the following artifacts from `./arduino-ide/electron/build/dist` to S3, but first, you must create the final channel file from the `latest-mac.yaml`: + - `arduino-ide_${VERSION}_macOS_arm64.dmg`, + - `arduino-ide_${VERSION}_macOS_arm64.zip`, and + - `stable-mac.yml` + - To create the final channel file, do the followings: + - Copy the `stable-mac.yml` file from the Mac Mini to a folder and rename it to `stable-mac-ARM64.yml`. + - Download the `stable-mac.yaml` produced by GitHub Actions from the latest release, rename it to `stable-mac-X64.yml`, and put it in the same folder where you put the file from the Mac Mini. + - Run the channel file merger: + ```sh + node ./scripts/merge-channel-files.js ./path/to/folder/with/channel/files + ``` + - You have the merged channel file that you need to upload to S3. + +### FAQ + - Q: I see no `stable` channel files, only `latest`. + - A: You forgot to set the `CI=true` environment variable. + +---- + + - Q: How to connect to the EC2 instance? + - A: DevOps will give you a temporary link to the private key. Create a file `username_ip.pem` in your cwd, copy the private key into the file, open a shell, and execute `ssh -i "username_ip.pem" username@ip`. DevOps will tell you the `username` and the `ip`. Do not forget the VPN. + +---- + + - Q: How to download the files from the EC2 instance? + - A: `scp -i username_ip.pem username@ip:/path/to/build/artifact /local/dir`. \ No newline at end of file diff --git a/package.json b/package.json index 2995fd68f..e9afbebc1 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "eslint-plugin-unused-imports": "^2.0.0", "husky": "^6.0.0", "ignore-styles": "^5.0.1", + "js-yaml": "^4.1.0", "lerna": "^6.1.0", "lint-staged": "^11.0.0", "node-gyp": "^9.3.0", diff --git a/scripts/merge-channel-files.js b/scripts/merge-channel-files.js new file mode 100644 index 000000000..4b83905a9 --- /dev/null +++ b/scripts/merge-channel-files.js @@ -0,0 +1,48 @@ +// @ts-check + +// The script should be invoked with the path to a folder that contains the two files as an argument. The filenames in the folder should be: +// - stable-mac-X64.yml +// - stable-mac-ARM64.yml +// The merged file will be saved to the folder with the name stable-mac.yml and that file can then be uploaded to S3 +// The input files will be deleted if the `--no-cleanup` argument is missing. +// Usage `node ./scripts/merge-channel-files.js ./path/to/folder/with/channel/files --no-cleanup` + +const yaml = require('js-yaml'); +const fs = require('fs'); +const path = require('path'); + +const args = process.argv.slice(2) +if (args.length < 1) { + console.error('Missing channel files folder path argument.'); + process.exit(1); +} + +const [channelFilesFolder,] = args; +// Staging file filename suffixes are named according to `runner.arch`. +// https://docs.github.com/en/actions/learn-github-actions/contexts#runner-context +const x86ChannelFilePath = path.join(channelFilesFolder, 'stable-mac-X64.yml'); +const arm64ChannelFilePath = path.join( + channelFilesFolder, + 'stable-mac-ARM64.yml' +); + +const x86Data = yaml.load( + fs.readFileSync(x86ChannelFilePath, { encoding: 'utf8' }) +); +const arm64Data = yaml.load( + fs.readFileSync(arm64ChannelFilePath, { encoding: 'utf8' }) +); + +const mergedData = x86Data; +mergedData['files'] = mergedData['files'].concat(arm64Data['files']); + +fs.writeFileSync( + path.join(channelFilesFolder, 'stable-mac.yml'), + yaml.dump(mergedData, { lineWidth: -1 }) +); + +// Clean up +if (!process.argv.includes('--no-cleanup')) { + fs.rmSync(x86ChannelFilePath); + fs.rmSync(arm64ChannelFilePath); +} diff --git a/scripts/update-version.js b/scripts/update-version.js index fea65ed27..32b3db5a5 100644 --- a/scripts/update-version.js +++ b/scripts/update-version.js @@ -1,5 +1,7 @@ //@ts-check +// Usage `node ./scripts/update-version.js 2.1.3` + const fs = require('fs'); const path = require('path'); const semver = require('semver');