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

refactor: migrate Encryptor to TypeScript and increase PBKDF2 iterations number #8828

Closed
wants to merge 18 commits into from

Conversation

gantunesr
Copy link
Member

@gantunesr gantunesr commented Mar 4, 2024

Description

This PR introduces the following modifications

  • @metamask/keyring-controller bump from v8.1.0 to v9.0.0
  • Refactor the Encryptor class from JS to TS
  • Adds unit tests to the Encryptor class
  • Increases the number of iterations for PBKDF2 from 5.000 to 900.000

CHANGELOG from @metamask/keyring-controller

Added,

  • Add KeyringController:persistAllKeyrings messenger action (#1965)

Changed,

  • BREAKING Change encryptor constructor option property type to GenericEncryptor | ExportableKeyEncryptor | > undefined (#2041)
    • When the controller is instantiated with cacheEncryptionKey: true, encryptor may no longer be of type GenericEncryptor.
  • Bump dependency on @metamask/scure-bip39 2.1.1 (#1868)
  • Bump dependency on @metamask/utils to 8.2.0 (#1957)
  • Bump @metamask/eth-keyring-controller to 14.0.0 (#1771)

Related issues

Progresses: https://github.com/MetaMask/accounts-planning/issues/100

Manual testing steps

Test case 1: Upgrade the client from the current version to feature branch
  1. Install the current version of MM mobile or the last commit in the main branch
  2. Create or import a wallet and verify it is correctly created
  3. Lock the wallet
  4. Upgrade the app to this feature branch
  5. Unlock the wallet, it should unlock the wallet
Test case 2: Lock and unlock the wallet
  1. Create or import a wallet and verify it is correctly created
  2. Lock the wallet
  3. Unlock the wallet, it should unlock the wallet
Test case 3: Reveal SRP and private key
  1. Create or import a wallet and verify it is correctly created
  2. Go to Settings > Security & Privacy
  3. Reveal the SRP, it should show the correct SRP
  4. Go back to Security & Privacy
  5. Reveal the private key of the current account
Test case 4: Connect QR wallet
  1. Create or import a wallet and verify it is correctly created
  2. Connect QR wallet and import 2 or more accounts
Test case 5: Connect Ledger wallet
  1. Create or import a wallet and verify it is correctly created
  2. Connect Ledger wallet and import the account
Test case 6: Sign a transaction with each account type
  1. Create or import a wallet and verify it is correctly created
  2. Connect Ledger wallet and import the account
  3. Connect QR wallet and import 2 or more accounts
  4. Send a transaction in a test network using each account type (HD, QR, and Ledger)
Test case 7: Sign a different messages with each account type
  1. Create or import a wallet and verify it is correctly created
  2. Connect Ledger wallet and import the account
  3. Connect QR wallet and import 2 or more accounts
  4. Go to MM E2E Test Dapp and sign different messages (Eth Sign, Personal Sign, Sign Typed Data, Sign Typed Data V3, Sign Typed Data V4, Sign Permit, Sign In With Ethereum) with each account (HD, QR, and Ledger). Note: Some methods are not supported in Ledger
Test case 8: Change password
Test case 9: Unlock with biometrics
Test case 10: Remember me
Test case 11: Onboarding with biometrics

Unit Tests and Coverage

yarn jest -u app/core/Encryptor/Encryptor.test.ts --collectCoverage --collectCoverageFrom=app/core/Encryptor/Encryptor.ts
=============================== Coverage summary ===============================
Statements   : 100% ( 46/46 )
Branches     : 94.73% ( 18/19 )
Functions    : 100% ( 14/14 )
Lines        : 100% ( 45/45 )
================================================================================

Screenshots/Recordings

Not applicable. No changes to the UI/UX.

Pre-merge author checklist

  • I’ve followed MetaMask Coding Standards.
  • I've clearly explained what problem this PR is solving and how it is solved.
  • I've linked related issues
  • I've included manual testing steps
  • I've included screenshots/recordings if applicable
  • I’ve included tests if applicable
  • I’ve documented my code using JSDoc format if applicable
  • I’ve applied the right labels on the PR (see labeling guidelines). Not required for external contributors.
  • I’ve properly set the pull request status:
    • In case it's not yet "ready for review", I've set it to "draft".
    • In case it's "ready for review", I've changed it from "draft" to "non-draft".

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Copy link

socket-security bot commented Mar 4, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@metamask/[email protected] Transitive: network +9 1.61 MB metamaskbot
npm/@metamask/[email protected] None +27 2.29 MB metamaskbot

🚮 Removed packages: npm/@metamask/[email protected], npm/@metamask/[email protected]

View full report↗︎

Copy link

socket-security bot commented Mar 4, 2024

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

Ignoring: npm/@metamask/[email protected], npm/@metamask/[email protected]

View full report↗︎

Next steps

Take a deeper look at the dependency

Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev.

Remove the package

If you happen to install a dependency that Socket reports as Known Malware you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency.

Mark a package as acceptable risk

To ignore an alert, reply with a comment starting with @SocketSecurity ignore followed by a space separated list of ecosystem/package-name@version specifiers. e.g. @SocketSecurity ignore npm/[email protected] or ignore all packages with @SocketSecurity ignore-all

@codecov-commenter
Copy link

codecov-commenter commented Mar 5, 2024

Codecov Report

Attention: Patch coverage is 96.42857% with 2 lines in your changes are missing coverage. Please review.

Project coverage is 45.68%. Comparing base (9339770) to head (a91de73).

Files Patch % Lines
app/core/Encryptor/Encryptor.ts 97.95% 1 Missing ⚠️
app/util/validators/index.js 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8828      +/-   ##
==========================================
+ Coverage   45.58%   45.68%   +0.10%     
==========================================
  Files        1276     1277       +1     
  Lines       31301    31326      +25     
  Branches     3202     3211       +9     
==========================================
+ Hits        14269    14312      +43     
+ Misses      16186    16168      -18     
  Partials      846      846              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@gantunesr
Copy link
Member Author

@SocketSecurity ignore npm/@metamask/[email protected]

@gantunesr gantunesr marked this pull request as ready for review March 7, 2024 01:07
@gantunesr gantunesr requested a review from a team as a code owner March 7, 2024 01:07
@github-actions github-actions bot added the Run Smoke E2E Triggers smoke e2e on Bitrise label Mar 7, 2024
Copy link
Contributor

github-actions bot commented Mar 7, 2024

https://bitrise.io/ Bitrise

❌❌❌ pr_smoke_e2e_pipeline failed on Bitrise! ❌❌❌

Commit hash: e96b45d
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/c77c13c3-1b99-4e04-9be1-0dc75718c76c

Note

  • You can kick off another pr_smoke_e2e_pipeline on Bitrise by removing and re-applying the Run Smoke E2E label on the pull request

@gantunesr
Copy link
Member Author

@SocketSecurity ignore npm/@babel/[email protected]
@SocketSecurity ignore npm/[email protected]
@SocketSecurity ignore npm/@babel/[email protected]

@gantunesr
Copy link
Member Author

Those dependencies were not introduced in this PR

@gantunesr gantunesr added Run Smoke E2E Triggers smoke e2e on Bitrise and removed Run Smoke E2E Triggers smoke e2e on Bitrise labels Mar 7, 2024
@gantunesr gantunesr self-assigned this Mar 7, 2024
Copy link
Contributor

github-actions bot commented Mar 7, 2024

https://bitrise.io/ Bitrise

❌❌❌ pr_smoke_e2e_pipeline failed on Bitrise! ❌❌❌

Commit hash: cbbd8c9
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/ef32072a-066e-4788-9ec3-0db777ccf3f7

Note

  • You can kick off another pr_smoke_e2e_pipeline on Bitrise by removing and re-applying the Run Smoke E2E label on the pull request

@danroc
Copy link
Contributor

danroc commented Mar 8, 2024

I think we could use a more explicit PR name, something like:

refactor: migrate Encryptor to TypeScript and increase PBKDF2 iterations number

WDYT?

app/core/Encryptor/Encryptor.ts Outdated Show resolved Hide resolved
app/core/Encryptor/Encryptor.ts Outdated Show resolved Hide resolved
app/core/Encryptor/constants.ts Outdated Show resolved Hide resolved
app/util/test/testSetup.js Outdated Show resolved Hide resolved
app/core/Encryptor/constants.ts Outdated Show resolved Hide resolved
app/core/Encryptor/Encryptor.ts Show resolved Hide resolved
app/core/Encryptor/Encryptor.test.ts Show resolved Hide resolved
app/core/Encryptor/Encryptor.ts Outdated Show resolved Hide resolved
app/core/Encryptor/Encryptor.ts Outdated Show resolved Hide resolved
app/core/Encryptor/Encryptor.ts Show resolved Hide resolved
@gantunesr gantunesr changed the title refactor: encryptor refactor: migrate Encryptor to TypeScript and increase PBKDF2 iterations number Mar 8, 2024
@gantunesr gantunesr added Run Smoke E2E Triggers smoke e2e on Bitrise and removed Run Smoke E2E Triggers smoke e2e on Bitrise labels Mar 8, 2024
Copy link
Contributor

github-actions bot commented Mar 8, 2024

https://bitrise.io/ Bitrise

✅✅✅ pr_smoke_e2e_pipeline passed on Bitrise! ✅✅✅

Commit hash: 07d26b0
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/e86ab7e6-a9dd-40ea-ba52-ffc73cf1d309

Note

  • You can kick off another pr_smoke_e2e_pipeline on Bitrise by removing and re-applying the Run Smoke E2E label on the pull request

@gantunesr gantunesr added Run Smoke E2E Triggers smoke e2e on Bitrise and removed Run Smoke E2E Triggers smoke e2e on Bitrise labels Mar 8, 2024
@gantunesr gantunesr removed the request for review from a team March 26, 2024 22:32
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

Copy link

sonarcloud bot commented Mar 27, 2024

@gantunesr
Copy link
Member Author

Diff between branches refactor/encryptor and refactor/encryptor-class (#9093)

git diff refactor/encryptor  refactor/encryptor-class
diff --git a/yarn.lock b/yarn.lock
index c3207f56c..c087ed70a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4052,16 +4052,6 @@
     "@metamask/safe-event-emitter" "^3.0.0"
     "@metamask/utils" "^8.3.0"

-"@metamask/json-rpc-middleware-stream@^6.0.2":
-  version "6.0.2"
-  resolved "https://registry.yarnpkg.com/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-6.0.2.tgz#75852ce481f8f9f091edbfc04ffdf964f8f3cabd"
-  integrity sha512-jtyx3PRfc1kqoLpYveIVQNwsxYKefc64/LCl9h9Da1m3nUKEvypbYuXSIwi237qvOjKmNHQKsDOZg6f4uBf62Q==
-  dependencies:
-    "@metamask/json-rpc-engine" "^7.3.2"
-    "@metamask/safe-event-emitter" "^3.0.0"
-    "@metamask/utils" "^8.3.0"
-    readable-stream "^3.6.2"
-
 "@metamask/key-tree@^9.0.0":
   version "9.0.0"
   resolved "https://registry.yarnpkg.com/@metamask/key-tree/-/key-tree-9.0.0.tgz#ce880a79f35af5b3b540b44be16ff98cc77be4c1"
@@ -4087,13 +4077,13 @@
     uuid "^9.0.0"

 "@metamask/keyring-api@^4.0.0":
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/@metamask/keyring-api/-/keyring-api-4.0.2.tgz#dc7ba93cf5cfd381c091dc231895dcfef72affc8"
-  integrity sha512-5Jc376i2ULXEopi5S6y/BZzloW4lrNOatMczKrsYVMiJdTHYZh9nPZY41ggZVxM1zwETvCQAX+QrAV2FXZQxAw==
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/@metamask/keyring-api/-/keyring-api-4.0.0.tgz#5e9eba65d6db56c2a64d4eaae2ba26d0ded036e2"
+  integrity sha512-wkApdp5UOwmPW4SuX+bj9vu73hxNzzrFBnwvDA0HN7oIiCDSH/97o8C5LsZ7Hmn6YplMEwOl28AhuQgFjOR2+w==
   dependencies:
-    "@metamask/providers" "^15.0.0"
-    "@metamask/snaps-sdk" "^3.1.1"
-    "@metamask/utils" "^8.3.0"
+    "@metamask/providers" "^14.0.1"
+    "@metamask/snaps-sdk" "^1.3.2"
+    "@metamask/utils" "^8.1.0"
     "@types/uuid" "^9.0.1"
     superstruct "^1.0.3"
     uuid "^9.0.0"
@@ -4354,42 +4344,6 @@
     readable-stream "^3.6.2"
     webextension-polyfill "^0.10.0"

-"@metamask/providers@^15.0.0":
-  version "15.0.0"
-  resolved "https://registry.yarnpkg.com/@metamask/providers/-/providers-15.0.0.tgz#e8957bb89d2f3379b32b60117d79a141e44db2bc"
-  integrity sha512-FXvL1NQNl6I7fMOJTfQYcBlBZ33vSlm6w80cMpmn8sJh0Lb7wcBpe02UwBsNlARnI+Qsr26XeDs6WHUHQh8CuA==
-  dependencies:
-    "@metamask/json-rpc-engine" "^7.3.2"
-    "@metamask/json-rpc-middleware-stream" "^6.0.2"
-    "@metamask/object-multiplex" "^2.0.0"
-    "@metamask/rpc-errors" "^6.2.1"
-    "@metamask/safe-event-emitter" "^3.0.0"
-    "@metamask/utils" "^8.3.0"
-    detect-browser "^5.2.0"
-    extension-port-stream "^3.0.0"
-    fast-deep-equal "^3.1.3"
-    is-stream "^2.0.0"
-    readable-stream "^3.6.2"
-    webextension-polyfill "^0.10.0"
-
-"@metamask/providers@^16.0.0":
-  version "16.0.0"
-  resolved "https://registry.yarnpkg.com/@metamask/providers/-/providers-16.0.0.tgz#5ba3bcbdc59b334958f1dcf6ed9b7f68de55eff1"
-  integrity sha512-zqZpn7Tg+QuvhL9x1WYCdXjFclZrMR2LOU2a3kHVFms5pOfizzFApB492VFgHuv/5xKohSxDkhXpAZ/TNGmM4g==
-  dependencies:
-    "@metamask/json-rpc-engine" "^7.3.2"
-    "@metamask/json-rpc-middleware-stream" "^6.0.2"
-    "@metamask/object-multiplex" "^2.0.0"
-    "@metamask/rpc-errors" "^6.2.1"
-    "@metamask/safe-event-emitter" "^3.0.0"
-    "@metamask/utils" "^8.3.0"
-    detect-browser "^5.2.0"
-    extension-port-stream "^3.0.0"
-    fast-deep-equal "^3.1.3"
-    is-stream "^2.0.0"
-    readable-stream "^3.6.2"
-    webextension-polyfill "^0.10.0"
-
 "@metamask/react-native-button@^3.0.0":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@metamask/react-native-button/-/react-native-button-3.0.0.tgz#4af8affd11e2b285cfc1b1752280797e1b33e62b"
@@ -4540,18 +4494,6 @@
     fast-xml-parser "^4.3.4"
     superstruct "^1.0.3"

-"@metamask/snaps-sdk@^3.1.1":
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/@metamask/snaps-sdk/-/snaps-sdk-3.2.0.tgz#66d60869697a479a3484adc9532d82c3b568fc19"
-  integrity sha512-Xfsc6seyucs7TP2JLXoKYrWm5FbrttdHnMOTfuzTb4T+qmdmoc3wdw83RAGjRFiOOaHGFc6JJSCdP33fBmw4Hg==
-  dependencies:
-    "@metamask/key-tree" "^9.0.0"
-    "@metamask/providers" "^16.0.0"
-    "@metamask/rpc-errors" "^6.2.1"
-    "@metamask/utils" "^8.3.0"
-    fast-xml-parser "^4.3.4"
-    superstruct "^1.0.3"
-
 "@metamask/snaps-utils@^5.1.2":
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/@metamask/snaps-utils/-/snaps-utils-5.2.0.tgz#ff43b97ff176846230d8bdedb1769b269effc4d8"
@@ -26144,7 +26086,7 @@ string-range@~1.2, string-range@~1.2.1:
   resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd"
   integrity sha1-qJPtNH5yKZvIO++78qaSqNI51d0=

-"string-width-cjs@npm:string-width@^4.2.0":
+"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -26162,15 +26104,6 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"

-"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
-  version "4.2.3"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
-  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
-  dependencies:
-    emoji-regex "^8.0.0"
-    is-fullwidth-code-point "^3.0.0"
-    strip-ansi "^6.0.1"
-
 string-width@^2.0.0, string-width@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
@@ -26285,14 +26218,7 @@ stringify-object@^3.3.0:
     is-obj "^1.0.1"
     is-regexp "^1.0.0"

-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
-  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
-  dependencies:
-    ansi-regex "^5.0.1"
-
-[email protected], strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", [email protected], strip-ansi@^6.0.0, strip-ansi@^6.0.1:
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -28184,7 +28110,8 @@ wordwrap@^1.0.0:
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
   integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==

-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+  name wrap-ansi-cjs
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
   integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -28219,15 +28146,6 @@ wrap-ansi@^6.2.0:
     string-width "^4.1.0"
     strip-ansi "^6.0.0"

-wrap-ansi@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
-  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
-  dependencies:
-    ansi-styles "^4.0.0"
-    string-width "^4.1.0"
-    strip-ansi "^6.0.0"
-
 wrap-ansi@^8.1.0:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"

Gudahtt added a commit that referenced this pull request Apr 12, 2024
There have been type errors showing up on some PRs relating to image
imports; TypeScript interprets them as strings, but we have them typed
as `ImageSourcePropType`. The mismatch is there because these image
imports are modified later in the build system.

Normally this is handled by our type declarations, which declare
upfront which types these imports should have. But on some PRs, it
seems that TypeScript will evaluate these declarations too late, after
files including image imports.

I had trouble reproducing this problem on `main`, but it can be seen
in the PR #8828 (commit b027cfa). If
you include this change on that branch, it resolves the problem.
@gantunesr
Copy link
Member Author

Closed in favour of #9093

@gantunesr gantunesr closed this Apr 12, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
QA Passed A successful QA run through has been done Run Smoke E2E Triggers smoke e2e on Bitrise team-accounts
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

9 participants