Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore Release 7.4.0 #15456

Merged
merged 7 commits into from
Jul 23, 2024
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
83 changes: 69 additions & 14 deletions .github/workflows/app-test-build-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
backend-unit-test:
strategy:
matrix:
os: ['windows-2022', 'ubuntu-22.04', 'macos-11']
os: ['windows-2022', 'ubuntu-22.04', 'macos-latest']
name: 'opentrons app backend unit tests on ${{matrix.os}}'
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -184,36 +184,57 @@ jobs:
echo "both develop builds for edge"
echo 'variants=["release", "internal-release"]' >> $GITHUB_OUTPUT
echo 'type=develop' >> $GITHUB_OUTPUT
elif [ "${{ format('{0}', endsWith(github.ref, 'app-build-internal')) }}" = "true" ] ; then
echo "internal-release builds for app-build-internal suffixes"
elif [ "${{ format('{0}', contains(github.ref, 'app-build-internal')) }}" = "true" ] ; then

echo 'variants=["internal-release"]' >> $GITHUB_OUTPUT
echo 'type=develop' >> $GITHUB_OUTPUT
elif [ "${{ format('{0}', endsWith(github.ref, 'app-build')) }}" = "true" ] ; then
echo "release develop builds for app-build suffixes"
if [ "${{ format('{0}', contains(github.ref, 'as-release')) }}" = "true" ] ; then
echo "internal-release as-release builds for app-build-internal + as-release suffixes"
echo 'type=as-release' >> $GITHUB_OUTPUT
else
echo "internal-release develop builds for app-build-internal suffixes"
echo 'type=develop' >> $GITHUB_OUTPUT
fi
elif [ "${{ format('{0}', contains(github.ref, 'app-build')) }}" = "true" ] ; then
echo 'variants=["release"]' >> $GITHUB_OUTPUT
echo 'type=develop' >> $GITHUB_OUTPUT
elif [ "${{ format('{0}', endsWith(github.ref, 'app-build-both')) }}" = "true" ] ; then
echo "Both develop builds for app-build-both suffixes"
if [ "${{ format('{0}', contains(github.ref, 'as-release')) }}" = "true" ] ; then
echo "release as-release builds for app-build + as-release suffixes"
echo 'type=as-release' >> $GITHUB_OUTPUT
else
echo "release develop builds for app-build suffixes"
echo 'type=develop' >> $GITHUB_OUTPUT
fi
elif [ "${{ format('{0}', contains(github.ref, 'app-build-both')) }}" = "true" ] ; then

echo 'variants=["release", "internal-release"]' >> $GITHUB_OUTPUT
echo 'type=develop' >> $GITHUB_OUTPUT
if [ "${{ format('{0}', contains(github.ref, 'as-release')) }}" = "true" ] ; then
echo "Both as-release builds for app-build-both + as-release suffixes"
echo 'type=as-release' >> $GITHUB_OUTPUT
else
echo "Both develop builds for app-build-both + as-release suffixes"
echo 'type=develop' >> $GITHUB_OUTPUT
fi
else
echo "No build for ref ${{github.ref}} and event ${{github.event_type}}"
echo 'variants=[]' >> $GITHUB_OUTPUT
echo 'type=develop' >> $GITHUB_OUTPUT
fi

- name: set summary
run: |
echo 'Type: ${{steps.determine-build-type.outputs.type}} Variants: ${{steps.determine-build-type.outputs.variants}}' >> $GITHUB_STEP_SUMMARY

build-app:
needs: [determine-build-type]
if: needs.determine-build-type.outputs.variants != '[]'
strategy:
matrix:
os: ['windows-2022', 'ubuntu-22.04', 'macos-11']
os: ['windows-2022', 'ubuntu-22.04', 'macos-latest']
variant: ${{fromJSON(needs.determine-build-type.outputs.variants)}}
target: ['desktop', 'odd']
exclude:
- os: 'windows-2022'
target: 'odd'
- os: 'macos-11'
- os: 'macos-latest'
target: 'odd'

runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -276,15 +297,49 @@ jobs:
npm config set cache ${{ github.workspace }}/.npm-cache
yarn config set cache-folder ${{ github.workspace }}/.yarn-cache
make setup-js

- 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 }}" | base64 --decode > /d/Certificate_pkcs12.p12
echo "${{ secrets.WINDOWS_CSC_B64}}" | 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 }}
SM_CLIENT_CERT_FILE: "D:\\Certificate_pkcs12.p12"
SM_CLIENT_CERT_PASSWORD: ${{secrets.SM_CLIENT_CERT_PASSWORD}}
SM_API_KEY: ${{secrets.SM_API_KEY}}
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}}" -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

# build the desktop app and deploy it
- name: 'build ${{matrix.variant}} app for ${{ matrix.os }}'
if: matrix.target == 'desktop'
timeout-minutes: 60
env:
OT_APP_MIXPANEL_ID: ${{ secrets.OT_APP_MIXPANEL_ID }}
OT_APP_INTERCOM_ID: ${{ secrets.OT_APP_INTERCOM_ID }}
WIN_CSC_LINK: ${{ secrets.OT_APP_CSC_WINDOWS }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.OT_APP_CSC_KEY_WINDOWS }}
WINDOWS_SIGN: ${{ format('{0}', contains(needs.determine-build-type.outputs.type, 'release')) }}
SM_HOST: ${{secrets.SM_HOST}}
SM_CLIENT_CERT_FILE: "D:\\Certificate_pkcs12.p12"
SM_CLIENT_CERT_PASSWORD: ${{secrets.SM_CLIENT_CERT_PASSWORD}}
SM_API_KEY: ${{secrets.SM_API_KEY}}
SM_CODE_SIGNING_CERT_SHA1_HASH: ${{secrets.SM_CODE_SIGNING_CERT_SHA1_HASH}}
SM_KEYPAIR_ALIAS: ${{secrets.SM_KEYPAIR_ALIAS}}
WINDOWS_CSC_FILEPATH: "D:\\opentrons_labworks_inc.crt"
CSC_LINK: ${{ secrets.OT_APP_CSC_MACOS }}
CSC_KEY_PASSWORD: ${{ secrets.OT_APP_CSC_KEY_MACOS }}
APPLE_ID: ${{ secrets.OT_APP_APPLE_ID }}
Expand Down
11 changes: 11 additions & 0 deletions api/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ log][]. For a list of currently known issues, please see the [Opentrons issue tr

---

## Opentrons Robot Software Changes in 7.4.0

Welcome to the v7.4.0 release of the Opentrons robot software!

This release adds support for the [Opentrons Flex HEPA/UV Module](https://opentrons.com/products/opentrons-flex-hepa-uv-module).

### Bug Fixes

- Fixed certain string runtime parameter values being misinterpreted as an incorrect type.
---

## Opentrons Robot Software Changes in 7.3.1

Welcome to the v7.3.1 release of the Opentrons robot software!
Expand Down
44 changes: 28 additions & 16 deletions api/src/opentrons/protocol_engine/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@
from datetime import datetime
from enum import Enum
from dataclasses import dataclass
from pydantic import BaseModel, Field, validator
from pydantic import (
BaseModel,
Field,
StrictBool,
StrictFloat,
StrictInt,
StrictStr,
validator,
)
from typing import Optional, Union, List, Dict, Any, NamedTuple, Tuple, FrozenSet
from typing_extensions import Literal, TypeGuard

Expand Down Expand Up @@ -877,12 +885,14 @@ def from_hw_state(cls, state: HwTipStateType) -> "TipPresenceStatus":
class RTPBase(BaseModel):
"""Parameters defined in a protocol."""

displayName: str = Field(..., description="Display string for the parameter.")
variableName: str = Field(..., description="Python variable name of the parameter.")
description: Optional[str] = Field(
displayName: StrictStr = Field(..., description="Display string for the parameter.")
variableName: StrictStr = Field(
..., description="Python variable name of the parameter."
)
description: Optional[StrictStr] = Field(
None, description="Detailed description of the parameter."
)
suffix: Optional[str] = Field(
suffix: Optional[StrictStr] = Field(
None,
description="Units (like mL, mm/sec, etc) or a custom suffix for the parameter.",
)
Expand All @@ -894,17 +904,17 @@ class NumberParameter(RTPBase):
type: Literal["int", "float"] = Field(
..., description="String specifying whether the number is an int or float type."
)
min: float = Field(
min: Union[StrictInt, StrictFloat] = Field(
..., description="Minimum value that the number param is allowed to have."
)
max: float = Field(
max: Union[StrictInt, StrictFloat] = Field(
..., description="Maximum value that the number param is allowed to have."
)
value: float = Field(
value: Union[StrictInt, StrictFloat] = Field(
...,
description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.",
)
default: float = Field(
default: Union[StrictInt, StrictFloat] = Field(
...,
description="Default value of the parameter, to be used when there is no client-specified value.",
)
Expand All @@ -916,11 +926,11 @@ class BooleanParameter(RTPBase):
type: Literal["bool"] = Field(
default="bool", description="String specifying the type of this parameter"
)
value: bool = Field(
value: StrictBool = Field(
...,
description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.",
)
default: bool = Field(
default: StrictBool = Field(
...,
description="Default value of the parameter, to be used when there is no client-specified value.",
)
Expand All @@ -929,8 +939,10 @@ class BooleanParameter(RTPBase):
class EnumChoice(BaseModel):
"""Components of choices used in RTP Enum Parameters."""

displayName: str = Field(..., description="Display string for the param's choice.")
value: Union[float, str] = Field(
displayName: StrictStr = Field(
..., description="Display string for the param's choice."
)
value: Union[StrictInt, StrictFloat, StrictStr] = Field(
..., description="Enum value of the param's choice."
)

Expand All @@ -945,11 +957,11 @@ class EnumParameter(RTPBase):
choices: List[EnumChoice] = Field(
..., description="List of valid choices for this parameter."
)
value: Union[float, str] = Field(
value: Union[StrictInt, StrictFloat, StrictStr] = Field(
...,
description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.",
)
default: Union[float, str] = Field(
default: Union[StrictInt, StrictFloat, StrictStr] = Field(
...,
description="Default value of the parameter, to be used when there is no client-specified value.",
)
Expand All @@ -958,5 +970,5 @@ class EnumParameter(RTPBase):
RunTimeParameter = Union[NumberParameter, EnumParameter, BooleanParameter]

RunTimeParamValuesType = Dict[
str, Union[float, bool, str]
StrictStr, Union[StrictInt, StrictFloat, StrictBool, StrictStr]
] # update value types as more RTP types are added
5 changes: 1 addition & 4 deletions app-shell/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ dist-posix: package-deps

.PHONY: dist-osx
dist-osx: package-deps
$(builder) --mac
$(builder) --mac --x64
$(MAKE) _dist-collect-artifacts

.PHONY: dist-linux
Expand All @@ -145,9 +145,6 @@ dist-ot3: package-deps
.PHONY: dist-macos-latest
dist-macos-latest: dist-osx

.PHONY: dist-macos-11
dist-macos-11: dist-osx

.PHONY: dist-ubuntu-latest
dist-ubuntu-latest: dist-linux

Expand Down
8 changes: 8 additions & 0 deletions app-shell/build/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ log][]. For a list of currently known issues, please see the [Opentrons issue tr

---

## Opentrons App Changes in 7.4.0

Welcome to the v7.4.0 release of the Opentrons App!

This release adds support for the [Opentrons Flex HEPA/UV Module](https://opentrons.com/products/opentrons-flex-hepa-uv-module).

---

## Opentrons App Changes in 7.3.1

Welcome to the v7.3.1 release of the Opentrons App!
Expand Down
6 changes: 6 additions & 0 deletions app-shell/electron-builder.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
} = process.env
const DEV_MODE = process.env.NODE_ENV !== 'production'
const USE_PYTHON = process.env.NO_PYTHON !== 'true'
const WINDOWS_SIGN = process.env.WINDOWS_SIGN === 'true'
const project = process.env.OPENTRONS_PROJECT ?? 'robot-stack'

// this will generate either
Expand Down Expand Up @@ -72,6 +73,11 @@ module.exports = async () => ({
target: ['nsis'],
publisherName: 'Opentrons Labworks Inc.',
icon: project === 'robot-stack' ? 'build/icon.ico' : 'build/three.ico',
forceCodeSigning: WINDOWS_SIGN,
rfc3161TimeStampServer: 'http://timestamp.digicert.com',
sign: 'scripts/windows-custom-sign.js',
signDlls: true,
signingHashAlgorithms: ['sha256'],
},
nsis: {
oneClick: false,
Expand Down
11 changes: 10 additions & 1 deletion app-shell/scripts/before-pack.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,16 @@ module.exports = function beforeBuild(context) {

// TODO(mc, 2022-05-16): explore virtualenvs for a more reliable
// implementation of this install
return execa(HOST_PYTHON, [
console.log(
`Installing python native deps using ${path.join(
PYTHON_DESTINATION,
'python3.10'
)}`
)
const invokablePython = platformName.includes('darwin')
? path.join(PYTHON_DESTINATION, 'python/bin/python3.10')
: HOST_PYTHON
return execa(invokablePython, [
'-m',
'pip',
'install',
Expand Down
62 changes: 62 additions & 0 deletions app-shell/scripts/windows-custom-sign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// from https://github.com/electron-userland/electron-builder/issues/7605

'use strict'

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

exports.default = async configuration => {
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
Loading