From ce020ed11ecf1437687ea1d86862f68fee965ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 15 Nov 2024 10:34:41 +0100 Subject: [PATCH 1/2] build(ci): Update CI workflow to target Node.js 23 and enhance binary signing and notarization process Implements #523 --- .github/workflows/ci.yaml | 62 +++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 35b2ebb..bc2031d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -107,17 +107,23 @@ jobs: - name: Build binaries run: | - pwd - ./node_modules/.bin/esbuild src/ctrl-q.js --bundle --external:axios --external:xdg-open --external:enigma.js --outfile=build.cjs --format=cjs --platform=node --target=node18 --minify --inject:./src/lib/util/import-meta-url.js --define:import.meta.url=import_meta_url - pkg --output "./${DIST_FILE_NAME}" -t node18-macos-x64 ./build.cjs --config package.json --compress GZip + # ------------------- + ./node_modules/.bin/esbuild src/ctrl-q.js --bundle --outfile=build.cjs --format=cjs --platform=node --target=node23 --inject:./src/lib/util/import-meta-url.js --define:import.meta.url=import_meta_url + node --experimental-sea-config sea-config.json + cp $(command -v node) ${DIST_FILE_NAME} + codesign --remove-signature ${DIST_FILE_NAME} + npx postject ctrl-q NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA - chmod +x "${DIST_FILE_NAME}" security delete-keychain build.keychain || true - # Turn our base64-encoded certificate back to a regular .p12 file + pwd + ls -la + # ------------------- + # Turn our base64-encoded certificate back to a regular .p12 file echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12 + # ------------------- # We need to create a new keychain, otherwise using the certificate will prompt # with a UI dialog asking for the certificate password, which we can't # use in a headless CI environment @@ -131,25 +137,33 @@ jobs: codesign --force -s "$MACOS_CERTIFICATE_NAME" -v "./${DIST_FILE_NAME}" --deep --strict --options=runtime --timestamp --entitlements ./release-config/${DIST_FILE_NAME}.entitlements + # ------------------- + # Notarize + # Store the notarization credentials so that we can prevent a UI password dialog from blocking the CI + echo "Create keychain profile" + xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" + + # ------------------- # We can't notarize an app bundle directly, but we need to compress it as an archive. # Therefore, we create a zip file containing our app bundle, so that we can send it to the # notarization service - - # Notarize release binary - echo "Creating temp notarization archive for release binary" - # ditto -c -k --keepParent "./${DIST_FILE_NAME}" "./${DIST_FILE_NAME}.zip" + # Notarize insider binary + echo "Creating temp notarization archive for insider build" ditto -c -k --keepParent "./${DIST_FILE_NAME}" "./${DIST_FILE_NAME}-${{ needs.release-please.outputs.release_version }}-macos.zip" # Here we send the notarization request to the Apple's Notarization service, waiting for the result. # This typically takes a few seconds inside a CI environment, but it might take more depending on the App # characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if # you're curious - echo "Notarize release app" + echo "Notarize insider app" xcrun notarytool submit "./${DIST_FILE_NAME}-${{ needs.release-please.outputs.release_version }}-macos.zip" --keychain-profile "notarytool-profile" --wait + # ------------------- + # Clean up # Delete build keychain security delete-keychain build.keychain + rm build.cjs - name: Upload to existing release uses: ncipollo/release-action@v1 @@ -216,8 +230,23 @@ jobs: - name: Build binaries run: | - ./node_modules/.bin/esbuild src/ctrl-q.js --bundle --external:axios --external:xdg-open --external:enigma.js --outfile=build.cjs --format=cjs --platform=node --target=node18 --minify --inject:./src/lib/util/import-meta-url.js --define:import.meta.url=import_meta_url - pkg --output "./${env:DIST_FILE_NAME}.exe" -t node18-win-x64 ./build.cjs --config package.json --compress GZip + ./node_modules/.bin/esbuild src/ctrl-q.js --bundle --outfile=build.cjs --format=cjs --platform=node --target=node23 --inject:./src/lib/util/import-meta-url.js --define:import.meta.url=import_meta_url + node --experimental-sea-config sea-config.json + node -e "require('fs').copyFileSync(process.execPath, 'ctrl-q.exe')" + + # Remove the signature from the executable + $processOptions1 = @{ + FilePath = "C:\Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/signtool.exe" + Wait = $true + ArgumentList = "remove", "/s", "./${env:DIST_FILE_NAME}.exe" + WorkingDirectory = "." + NoNewWindow = $true + } + Start-Process @processOptions1 + + npx postject ctrl-q.exe NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 + + dir # Sign the executable # 1st signing @@ -240,12 +269,13 @@ jobs: } Start-Process @processOptions2 - # Create release binary zip + # Create insider's build zip $compress = @{ Path = "./${env:DIST_FILE_NAME}.exe" CompressionLevel = "Fastest" DestinationPath = "${env:DIST_FILE_NAME}-${{ needs.release-please.outputs.release_version }}-win.zip" } + Compress-Archive @compress - name: Upload to existing release @@ -304,8 +334,10 @@ jobs: - name: Build binaries run: | - ./node_modules/.bin/esbuild src/ctrl-q.js --bundle --external:axios --external:xdg-open --external:enigma.js --outfile=build.cjs --format=cjs --platform=node --target=node18 --minify --inject:./src/lib/util/import-meta-url.js --define:import.meta.url=import_meta_url - pkg --output "./${DIST_FILE_NAME}" -t node18-linux-x64 ./build.cjs --config package.json --compress GZip + ./node_modules/.bin/esbuild src/ctrl-q.js --bundle --outfile=build.cjs --format=cjs --platform=node --target=node23 --inject:./src/lib/util/import-meta-url.js --define:import.meta.url=import_meta_url + node --experimental-sea-config sea-config.json + cp $(command -v node) ${DIST_FILE_NAME} + npx postject ctrl-q NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 chmod +x ${DIST_FILE_NAME} From 84ffc189d0249efac4728132574ae3ae29735674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 15 Nov 2024 10:36:52 +0100 Subject: [PATCH 2/2] chore(deps): update dependencies to latest versions --- package-lock.json | 79 +++++++++++++++++++++++++++-------------------- package.json | 10 +++--- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index a68c76e..5b6546f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.18.1", "license": "MIT", "dependencies": { - "@qlik/api": "^1.23.0", + "@qlik/api": "^1.24.0", "axios": "^1.7.7", "commander": "^12.1.0", "csv-parse": "^5.5.6", @@ -26,10 +26,10 @@ "retry-axios": "^3.1.3", "table": "^6.8.2", "text-treeview": "^1.0.2", - "undici": "^6.20.1", + "undici": "^6.21.0", "upath": "^2.0.1", - "uuid": "^11.0.0", - "winston": "^3.15.0", + "uuid": "^11.0.3", + "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0", "ws": "^8.18.0", "yesno": "^0.4.0" @@ -37,7 +37,7 @@ "devDependencies": { "@babel/eslint-parser": "^7.25.9", "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@eslint/js": "^9.13.0", + "@eslint/js": "^9.14.0", "@jest/globals": "^29.7.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", @@ -1281,9 +1281,9 @@ "peer": true }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "license": "MIT", "engines": { @@ -1803,9 +1803,9 @@ } }, "node_modules/@qlik/api": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@qlik/api/-/api-1.23.0.tgz", - "integrity": "sha512-QrwN7iQP5NYeAevbF9gBRzOnbKuV5MKUNXczyfqN3KnbDFCMRKi0BlwesHD15mdpkpydCd8A8uvPtkHz9OiT0Q==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@qlik/api/-/api-1.24.0.tgz", + "integrity": "sha512-TqN+DDk3x3T9xZBF9ULfctGP1Ki+isEqpAGVnRm5DEGlVBDIxxqpiuJLX9aJzKSnCfA7pXPuOsbLVJItgeVlOQ==", "license": "ISC", "dependencies": { "enigma.js": "^2.14.0", @@ -3023,6 +3023,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4712,9 +4723,9 @@ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" }, "node_modules/logform": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz", - "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", "license": "MIT", "dependencies": { "@colors/colors": "1.6.0", @@ -5309,9 +5320,10 @@ "dev": true }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -5866,9 +5878,9 @@ } }, "node_modules/undici": { - "version": "6.20.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz", - "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", + "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", "license": "MIT", "engines": { "node": ">=18.17" @@ -5935,9 +5947,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "node_modules/uuid": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.0.tgz", - "integrity": "sha512-iE8Fa5fgBY4rN5GvNUJ8TSwO1QG7TzdPfhrJczf6XJ6mZUxh/GX433N70fCiJL9h8EKP5ayEIo0Q6EBQGWHFqA==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -5992,22 +6004,22 @@ } }, "node_modules/winston": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz", - "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.6.0", + "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.7.0" + "winston-transport": "^4.9.0" }, "engines": { "node": ">= 12.0.0" @@ -6031,12 +6043,13 @@ } }, "node_modules/winston-transport": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", - "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", + "logform": "^2.7.0", + "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" }, "engines": { diff --git a/package.json b/package.json index 13d198e..88c9995 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "license": "MIT", "type": "module", "dependencies": { - "@qlik/api": "^1.23.0", + "@qlik/api": "^1.24.0", "axios": "^1.7.7", "commander": "^12.1.0", "csv-parse": "^5.5.6", @@ -47,10 +47,10 @@ "retry-axios": "^3.1.3", "table": "^6.8.2", "text-treeview": "^1.0.2", - "undici": "^6.20.1", + "undici": "^6.21.0", "upath": "^2.0.1", - "uuid": "^11.0.0", - "winston": "^3.15.0", + "uuid": "^11.0.3", + "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0", "ws": "^8.18.0", "yesno": "^0.4.0" @@ -58,7 +58,7 @@ "devDependencies": { "@babel/eslint-parser": "^7.25.9", "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@eslint/js": "^9.13.0", + "@eslint/js": "^9.14.0", "@jest/globals": "^29.7.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1",