Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 34 additions & 30 deletions .github/workflows/app-test-build-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ concurrency:
cancel-in-progress: true

env:
CI: "true"
CI: 'true'
_APP_DEPLOY_BUCKET_ROBOTSTACK: builds.opentrons.com
_APP_DEPLOY_FOLDER_ROBOTSTACK: app
_APP_DEPLOY_BUCKET_OT3: ot3-development.builds.opentrons.com
Expand Down Expand Up @@ -211,6 +211,32 @@ jobs:
python-version: '3.10'
- name: check make version
run: make --version
- name: 'Configure Windows code signing environment'
if: startsWith(matrix.os, 'windows') && contains(needs.determine-build-type.outputs.type, 'release')
shell: bash
run: |
echo "${{ secrets.SM_CLIENT_CERT_FILE_B64_V2 }}" | base64 --decode > /d/Certificate_pkcs12.p12
echo "${{ secrets.WINDOWS_CSC_B64_V2 }}" | base64 --decode > /d/opentrons_labworks_inc.crt
echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH
echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH
echo "C:\Program Files\DigiCert\DigiCert Keylocker Tools" >> $GITHUB_PATH

- name: 'Setup Windows code signing helpers'
if: startsWith(matrix.os, 'windows') && contains(needs.determine-build-type.outputs.type, 'release')
shell: cmd
env:
SM_HOST: ${{ secrets.SM_HOST_V2 }}
SM_CLIENT_CERT_FILE: "D:\\Certificate_pkcs12.p12"
SM_CLIENT_CERT_PASSWORD: ${{secrets.SM_CLIENT_CERT_PASSWORD_V2}}
SM_API_KEY: ${{secrets.SM_API_KEY_V2}}
run: |
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/Keylockertools-windows-x64.msi/download -H "x-api-key:${{secrets.SM_API_KEY_V2}}" -o Keylockertools-windows-x64.msi
msiexec /i Keylockertools-windows-x64.msi /quiet /qn
smksp_registrar.exe list
smctl.exe keypair ls
C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
smksp_cert_sync.exe
smctl.exe healthcheck --all

# Do the frontend dist bundle
- name: 'bundle ${{matrix.variant}} frontend'
Expand All @@ -221,32 +247,6 @@ jobs:
run: |
make -C app dist

- name: Install and Invoke TrustedSigning @0.5.3 on dummy executable
# Work around from https://github.com/electron-userland/electron-builder/issues/9076#issuecomment-2855541018
if: startsWith(matrix.os, 'windows') && contains(needs.determine-build-type.outputs.type, 'release')
shell: pwsh
run: |
Install-Module -Name TrustedSigning -RequiredVersion 0.5.3 -Force -Repository PSGallery
# Create a dummy executable file
$dummyExePath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath "dummy.exe"
Set-Content -Path $dummyExePath -Value "This is a dummy executable for testing purposes."
# Invoke Trusted Signing on the dummy executable
# Necessary to force dependency resolution
try {
Invoke-TrustedSigning `
-Endpoint 'https://eus.codesigning.azure.net/' `
-CertificateProfileName 'dummyName' `
-CodeSigningAccountName 'dummyName' `
-TimestampRfc3161 'http://timestamp.acs.microsoft.com' `
-TimestampDigest 'SHA256' `
-FileDigest 'SHA256' `
-Files $dummyExePath
} catch {
Write-Host "Invoke-TrustedSigning failed: $($_.Exception.Message)"
# Prevent the script from exiting with a non-zero status
exit 0
}

# build the desktop app and deploy it
- name: 'build ${{matrix.variant}} app for ${{ matrix.os }}'
if: matrix.target == 'desktop'
Expand All @@ -255,9 +255,13 @@ jobs:
OT_APP_MIXPANEL_ID: ${{ secrets.OT_APP_MIXPANEL_ID }}
OT_APP_INTERCOM_ID: ${{ secrets.OT_APP_INTERCOM_ID }}
WINDOWS_SIGN: ${{ format('{0}', contains(needs.determine-build-type.outputs.type, 'release')) }}
AZURE_TENANT_ID: ${{secrets.AZURE_TENANT_ID}}
AZURE_CLIENT_ID: ${{secrets.AZURE_CLIENT_ID}}
AZURE_CLIENT_SECRET: ${{secrets.AZURE_CLIENT_SECRET}}
SM_CODE_SIGNING_CERT_SHA1_HASH: ${{secrets.SM_CODE_SIGNING_CERT_SHA1_HASH_V3}}
SM_KEYPAIR_ALIAS: ${{secrets.SM_KEYPAIR_ALIAS_V3}}
SM_HOST: ${{ secrets.SM_HOST_V2 }}
SM_CLIENT_CERT_FILE: "D:\\Certificate_pkcs12.p12"
SM_CLIENT_CERT_PASSWORD: ${{secrets.SM_CLIENT_CERT_PASSWORD_V2}}
SM_API_KEY: ${{secrets.SM_API_KEY_V2}}
WINDOWS_CSC_FILEPATH: "D:\\opentrons_labworks_inc.crt"
CSC_LINK: ${{ secrets.OT_APP_CSC_MACOS_V2 }}
CSC_KEY_PASSWORD: ${{ secrets.OT_APP_CSC_KEY_MACOS_V2 }}
APPLE_ID: ${{ secrets.OT_APP_APPLE_ID_V2 }}
Expand Down
10 changes: 5 additions & 5 deletions app-shell/electron-builder.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ module.exports = async () => ({
target: ['nsis'],
icon: project === 'robot-stack' ? 'build/icon.ico' : 'build/three.ico',
forceCodeSigning: WINDOWS_SIGN,
azureSignOptions: {
publisherName: 'OPENTRONS LABWORKS INC.',
codeSigningAccountName: 'desktop-app-signing',
certificateProfileName: 'OpentronsDesktopApp',
endpoint: 'https://eus.codesigning.azure.net',
signtoolOptions: {
publisherName: ['Opentrons Labworks Inc.', 'OPENTRONS LABWORKS INC.'],
rfc3161TimeStampServer: 'http://timestamp.digicert.com',
sign: 'scripts/windows-custom-sign.js',
signingHashAlgorithms: ['sha256'],
},
},
nsis: {
Expand Down
66 changes: 66 additions & 0 deletions app-shell/scripts/windows-custom-sign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// from https://github.com/electron-userland/electron-builder/issues/7605

'use strict'

const { execSync } = require('node:child_process')

exports.default = async configuration => {
const { WINDOWS_SIGN } = process.env
if (WINDOWS_SIGN !== 'true') {
return
}
const signCmd = `smctl sign --keypair-alias="${String(
process.env.SM_KEYPAIR_ALIAS
)}" --input "${String(configuration.path)}" --certificate="${String(
process.env.WINDOWS_CSC_FILEPATH
)}" --exit-non-zero-on-fail --failfast --verbose`
console.log(signCmd)
try {
const signProcess = execSync(signCmd, {
stdio: 'pipe',
})
console.log(`Sign success!`)
console.log(
`Sign stdout: ${signProcess?.stdout?.toString() ?? '<no output>'}`
)
console.log(
`Sign stderr: ${signProcess?.stderr?.toString() ?? '<no output>'}`
)
console.log(`Sign code: ${signProcess.code}`)
} catch (err) {
console.error(`Exception running sign: ${err.status}!
Process stdout:
${err?.stdout?.toString() ?? '<no output>'}
-------------
Process stderr:
${err?.stdout?.toString() ?? '<no output>'}
-------------
`)
throw err
}
const verifyCmd = `smctl sign verify --fingerprint="${String(
process.env.SM_CODE_SIGNING_CERT_SHA1_HASH
)}" --input="${String(configuration.path)}" --verbose`
console.log(verifyCmd)
try {
const verifyProcess = execSync(verifyCmd, { stdio: 'pipe' })
console.log(`Verify success!`)
console.log(
`Verify stdout: ${verifyProcess?.stdout?.toString() ?? '<no output>'}`
)
console.log(
`Verify stderr: ${verifyProcess?.stderr?.toString() ?? '<no output>'}`
)
} catch (err) {
console.error(`
Exception running verification: ${err.status}!
Process stdout:
${err?.stdout?.toString() ?? '<no output>'}
--------------
Process stderr:
${err?.stderr?.toString() ?? '<no output>'}
--------------
`)
throw err
}
}
Loading