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

[$250] [HOLD for payment 2024-10-22] Speed up Android builds #49567

Open
roryabraham opened this issue Sep 21, 2024 · 41 comments
Open

[$250] [HOLD for payment 2024-10-22] Speed up Android builds #49567

roryabraham opened this issue Sep 21, 2024 · 41 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Overdue

Comments

@roryabraham
Copy link
Contributor

roryabraham commented Sep 21, 2024

Problem

Android builds typically take 10-30 minutes on my M2 Mac, which is a long time.

Solution

Research ways to speed them up

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021856375406194339171
  • Upwork Job ID: 1856375406194339171
  • Last Price Increase: 2024-11-12
  • Automatic offers:
    • aimane-chnaif | Contributor | 104865138
Issue OwnerCurrent Issue Owner: @dukenv0307
@roryabraham roryabraham added the Monthly KSv2 label Sep 21, 2024
@roryabraham roryabraham self-assigned this Sep 21, 2024
@roryabraham roryabraham changed the title Try to speed up Android builds Speed up Android builds Sep 21, 2024
@roryabraham
Copy link
Contributor Author

roryabraham commented Sep 21, 2024

There are a few things I'd like to try:

  • Enable gradle build cache
  • Enable gradle configuration cache
  • Enable gradle parallel task execution
  • Enable ccache

@roryabraham
Copy link
Contributor Author

In order to be methodic and quantitative with these changes, I'll be using ./gradlew build --scan to generate detailed build scan reports.

@saifelance

This comment was marked as off-topic.

@roryabraham

This comment was marked as off-topic.

@roryabraham
Copy link
Contributor Author

Build scan for a clean ./gradlew assembleDebug (note: next time I should do active arch only, because that's what we do in dev)

https://scans.gradle.com/s/4e4x4kl55d3js

@roryabraham
Copy link
Contributor Author

roryabraham commented Sep 21, 2024

Another clean build scan, this time only one arch: https://scans.gradle.com/s/4apezfw7xtotm

Build command was: ./gradlew assembleDebug -PreactNativeArchitectures=arm64-v8a --scan

@roryabraham
Copy link
Contributor Author

A build scan with only this diff:

diff --git a/android/gradle.properties b/android/gradle.properties
index 87333d20f74..1f60a7d335d 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -55,3 +55,6 @@ MYAPP_UPLOAD_KEY_ALIAS=ReactNativeChat-Key-Alias
 disableFrameProcessors=true
 
 android.nonTransitiveRClass=false
+
+org.gradle.parallel=true

https://scans.gradle.com/s/67qe4vuqgytyq

@roryabraham
Copy link
Contributor Author

Adding the org.gradle.caching=true does not appear to be worth it, because:

  • It has no effect on the configuration phase, which consistently takes about 10 minutes while the build phase takes about 1 minute w/ parallel enabled.
  • Even a cached build seemed to take about a minute, but populating the cache takes longer

@roryabraham
Copy link
Contributor Author

roryabraham commented Sep 25, 2024

Going to try the configuration cache field with:

./gradlew assembleDebug --configuration-cache -PreactNativeArchitectures=arm64-v8a --scan

Edit: 2nd build w/ configuration cache enabled failed 😞

Logs
FAILURE: Build failed with an exception.

* Where:
Settings file '/Users/roryabraham/Expensidev/App/android/settings.gradle' line: 3

* What went wrong:
Configuration cache problems found in this build.

9752 problems were found storing the configuration cache, only the first 4096 were considered, 7 of which seem unique.
- Build file '../node_modules/@expensify/react-native-live-markdown/android/build.gradle': external process started 'node --print require.resolve('react-native/package.json')'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Build file 'app/build.gradle': external process started 'node --print require.resolve('@expo/cli')'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Build file 'app/build.gradle': external process started 'node -e require('expo/scripts/resolveAppEntry') /Users/roryabraham/Expensidev/App android absolute'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Build file 'build.gradle': external process started 'node --print JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Build file 'build.gradle': line 47: external process started 'node --print JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Settings file 'settings.gradle': line 26: external process started 'node --print require.resolve('expo/package.json')'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Settings file 'settings.gradle': line 3: external process started 'npx @react-native-community/cli config'
  See https://docs.gradle.org/8.8/userguide/configuration_cache.html#config_cache:requirements:external_processes

@roryabraham
Copy link
Contributor Author

roryabraham commented Sep 25, 2024

This branch enabling ccache for Android builds also does not seem to materially improve the configuration time. Not sure if it's all done correctly though

@roryabraham roryabraham removed the Reviewing Has a PR in review label Sep 26, 2024
@roryabraham
Copy link
Contributor Author

Another simple thing we could try is providing more RAM to the gradle build. Pretty sure it gets only 512MB by default. We could try bumping that to 2048 (or even higher) and see if it helps

@TMisiukiewicz
Copy link
Contributor

TMisiukiewicz commented Oct 1, 2024

Hey @roryabraham I did some investigation around ccache and build process

I have M1 Pro chip with 32gb memory

  1. Clean build
    ./gradlew assembleDevelopmentDebug -PreactNativeArchitectures=arm64-v8a
    Time: 9m 26s
    Scan: https://scans.gradle.com/s/lmlexejrgechm

  2. With ccache enabled (I followed the instruction from the docs, removed build folder and ran the same command again)
    ./gradlew assembleDevelopmentDebug -PreactNativeArchitectures=arm64-v8a
    Time: 8m 37s
    Scan: https://scans.gradle.com/s/qy7dw3faz4bjm

  3. With ccache and org.gradle.configureondemand=true set
    ./gradlew assembleDevelopmentDebug -PreactNativeArchitectures=arm64-v8a
    Time: 7m 35s
    Scan: https://scans.gradle.com/s/6ucqmx7zrnk7c

What i noticed, app:fullstoryDevelopmentDebug is taking 35s. However, we initialize fullstory only in production

init: () => {
Environment.getEnvironment().then((envName: string) => {
// We only want to start fullstory if the app is running in production
if (envName !== CONST.ENVIRONMENT.PRODUCTION) {
return;
}
FullStory.restart();
const [session] = useOnyx(ONYXKEYS.USER_METADATA);

So maybe there is a way we could exclude it from development builds?

  1. With ccache, org.gradle.configureondemand=true and with excluded fullstoryDevelopmentDebug
    ./gradlew assembleDevelopmentDebug -PreactNativeArchitectures=arm64-v8a -x fullstoryDevelopmentDebug
    Time: 6m 49s
    Scan: https://scans.gradle.com/s/b5ndxneeuyu7e

I was having the same errors when trying to use --configuration-cache flag, I'll try to investigate this tomorrow

@roryabraham
Copy link
Contributor Author

Nice investigation @TMisiukiewicz! Since ccache does seem to help, can you take a look at this draft PR? My goal with that was to:

  • enable ccache by default for debug builds
  • make it easy for developers to setup
  • reduce side-effects so that developing NewDot doesn't affect other projects

and the idea with the script is to setup symlinks as per the instructions in the RN docs, but then clean them up before the script exits using trap. I think it's a good idea, but there might be a couple bugs. Can you try it out please?

@gedu
Copy link
Contributor

gedu commented Oct 1, 2024

I got the next message:
Jetifier was enabled which means your builds are slower by 4-20%.

So I run a check, ./gradlew -Pandroid.enableJetifier=false checkJetifier

I disabled jetifier and check if other libs need it enabled, this is the result:


> Configure project :react-native-reanimated
Android gradle plugin: 8.5.0
Gradle: 8.8

> Configure project :react-native-vision-camera
[VisionCamera] react-native-worklets-core not found, Frame Processors disabled!

> Task :expo-asset:checkJetifier
Skipping ':expo-asset:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :app:checkJetifier
Skipping ':app:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expensify_react-native-live-markdown:checkJetifier
Skipping ':expensify_react-native-live-markdown:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expo-modules-core:checkJetifier
Skipping ':expo-modules-core:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expo:checkJetifier
Skipping ':expo:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expo-image-loader:checkJetifier
Skipping ':expo-image-loader:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expo-av:checkJetifier
Skipping ':expo-av:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expo-image:checkJetifier
Skipping ':expo-image:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :fullstory_react-native:checkJetifier
Skipping ':fullstory_react-native:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :expo-image-manipulator:checkJetifier
Skipping ':expo-image-manipulator:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-config:checkJetifier
Skipping ':react-native-config:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-community_netinfo:checkJetifier
Skipping ':react-native-community_netinfo:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-community_geolocation:checkJetifier
Skipping ':react-native-community_geolocation:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :onfido_react-native-sdk:checkJetifier
Skipping ':onfido_react-native-sdk:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-clipboard_clipboard:checkJetifier
Skipping ':react-native-clipboard_clipboard:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :invertase_react-native-apple-authentication:checkJetifier
Skipping ':invertase_react-native-apple-authentication:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-android-location-enabler:checkJetifier
Skipping ':react-native-android-location-enabler:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-camera-roll_camera-roll:checkJetifier
Skipping ':react-native-camera-roll_camera-roll:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-blob-util:checkJetifier
Skipping ':react-native-blob-util:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :lottie-react-native:checkJetifier
Skipping ':lottie-react-native:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-document-picker:checkJetifier
Skipping ':react-native-document-picker:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-device-info:checkJetifier
Skipping ':react-native-device-info:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-firebase_analytics:checkJetifier
Skipping ':react-native-firebase_analytics:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-firebase_app:checkJetifier
Skipping ':react-native-firebase_app:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-fs:checkJetifier
Skipping ':react-native-fs:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-gesture-handler:checkJetifier
Skipping ':react-native-gesture-handler:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-dev-menu:checkJetifier
Skipping ':react-native-dev-menu:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-image-size:checkJetifier
Skipping ':react-native-image-size:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-key-command:checkJetifier
Skipping ':react-native-key-command:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-firebase_crashlytics:checkJetifier
Skipping ':react-native-firebase_crashlytics:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-image-picker:checkJetifier
Skipping ':react-native-image-picker:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-haptic-feedback:checkJetifier
Skipping ':react-native-haptic-feedback:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-firebase_perf:checkJetifier
Skipping ':react-native-firebase_perf:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-google-signin_google-signin:checkJetifier
Skipping ':react-native-google-signin_google-signin:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-localize:checkJetifier
Skipping ':react-native-localize:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-pager-view:checkJetifier
Skipping ':react-native-pager-view:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-permissions:checkJetifier
Skipping ':react-native-permissions:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-keyboard-controller:checkJetifier
Skipping ':react-native-keyboard-controller:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-quick-sqlite:checkJetifier
Skipping ':react-native-quick-sqlite:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-launch-arguments:checkJetifier
Skipping ':react-native-launch-arguments:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-pdf:checkJetifier
Skipping ':react-native-pdf:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-picker_picker:checkJetifier
Skipping ':react-native-picker_picker:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-plaid-link-sdk:checkJetifier
Skipping ':react-native-plaid-link-sdk:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-performance:checkJetifier
Skipping ':react-native-performance:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-reanimated:checkJetifier
Skipping ':react-native-reanimated:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-screens:checkJetifier
Skipping ':react-native-screens:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-view-shot:checkJetifier
Skipping ':react-native-view-shot:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-vision-camera:checkJetifier
Skipping ':react-native-vision-camera:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-share:checkJetifier
Skipping ':react-native-share:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-safe-area-context:checkJetifier
Skipping ':react-native-safe-area-context:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-sound:checkJetifier
Skipping ':react-native-sound:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-svg:checkJetifier
Skipping ':react-native-svg:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-release-profiler:checkJetifier
Skipping ':react-native-release-profiler:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :react-native-webview:checkJetifier
Skipping ':react-native-webview:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :rnmapbox_maps:checkJetifier
Skipping ':rnmapbox_maps:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :ua_react-native-airship:checkJetifier
Skipping ':ua_react-native-airship:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

> Task :shopify_flash-list:checkJetifier
Skipping ':shopify_flash-list:checkJetifier' task as Jetifier is already disabled (android.enableJetifier=false).

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.8/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 7m 31s

All of the libs has the Jetifier disabled. Meaning that we can disable Jetifier doing

android.enableJetifier=false

That would save 5m, from 12m 50s to 7m 31s

Before: https://scans.gradle.com/s/4apezfw7xtotm
After: https://scans.gradle.com/s/nhpkhymscptae

@roryabraham
Copy link
Contributor Author

roryabraham commented Oct 1, 2024

@Julesssss can you comment on whether disabling jetifier is safe? Looks like it's already disabled for all those libs? So why was it taking so long? 😕

@TMisiukiewicz
Copy link
Contributor

Looks like Jetifier is also removed from the community template: react-native-community/template#9

@Julesssss
Copy link
Contributor

Wow, these are looking like great potential improvements.


It sounds like jetifier is removing deprecated support libraries and using shared AndroidX support libraries. I'm not sure why it added to build times, perhaps low level Android libraries also benefit from this 🤷 Anyway, the trade-off of packaging duplicate support libs seems worth the reduced build times.

My worry though is that HybridApp might depend on Jetifier. As the app was closer to native code, it's possible that we'd have to replace our AndroidX libraries usages with quite outdated libraries.

I think the next step would be to get HybridApp to build.

@TMisiukiewicz
Copy link
Contributor

@roryabraham I tried running your branch, here are the results:

I changed run-android.sh file to run ./gradlew assembleDevelopmentDebug -PreactNativeArchitectures=arm64-v8a --scan instead of run-android

  1. Clean build, clean ccache
    Scan: https://scans.gradle.com/s/f552tkilldsmk
    Time: 23m 56s

The time is kinda extreme here, usually it takes up to 15 minutes. CMake tasks were really long here.

  1. Removed app/build, ran the script again
    Scan: https://scans.gradle.com/s/xbr2oairlxaam
    Time: 8m 56s

ccache -s shows 6 hits

One thing that bothers me is the fact that I have to remember to run the script with sudo, otherwise I have to provide my password when creating and killing each symlink 😩
image

@roryabraham
Copy link
Contributor Author

Not sure if there's a good way to avoid that since I guess /usr/local/bin is privileged. Sudo must be required to setup ccache per the instructions from meta, no?

Copy link

melvin-bot bot commented Oct 10, 2024

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.0.47-4 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2024-10-17. 🎊

For reference, here are some details about the assignees on this issue:

  • @gedu does not require payment (Contractor)
  • @TMisiukiewicz does not require payment (Contractor)

@melvin-bot melvin-bot bot added Weekly KSv2 and removed Weekly KSv2 labels Oct 15, 2024
@melvin-bot melvin-bot bot changed the title [HOLD for payment 2024-10-17] [HOLD for payment 2024-10-14] Speed up Android builds [HOLD for payment 2024-10-22] [HOLD for payment 2024-10-17] [HOLD for payment 2024-10-14] Speed up Android builds Oct 15, 2024
Copy link

melvin-bot bot commented Oct 15, 2024

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.0.48-2 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2024-10-22. 🎊

For reference, here are some details about the assignees on this issue:

  • @gedu does not require payment (Contractor)
  • @TMisiukiewicz does not require payment (Contractor)

@aimane-chnaif
Copy link
Contributor

@Julesssss can you please reopen? C+ payment is remaining

@Julesssss Julesssss reopened this Oct 28, 2024
@Julesssss Julesssss changed the title [HOLD for payment 2024-10-22] [HOLD for payment 2024-10-17] [HOLD for payment 2024-10-14] Speed up Android builds [HOLD for payment 2024-10-22] Speed up Android builds Oct 28, 2024
@melvin-bot melvin-bot bot added the Overdue label Nov 11, 2024
@Julesssss Julesssss added the External Added to denote the issue can be worked on by a contributor label Nov 12, 2024
@melvin-bot melvin-bot bot changed the title [HOLD for payment 2024-10-22] Speed up Android builds [$250] [HOLD for payment 2024-10-22] Speed up Android builds Nov 12, 2024
Copy link

melvin-bot bot commented Nov 12, 2024

Job added to Upwork: https://www.upwork.com/jobs/~021856375406194339171

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Nov 12, 2024
Copy link

melvin-bot bot commented Nov 12, 2024

Triggered auto assignment to Contributor-plus team member for initial proposal review - @dukenv0307 (External)

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 Overdue labels Nov 12, 2024
@Julesssss Julesssss added the Bug Something is broken. Auto assigns a BugZero manager. label Nov 12, 2024
Copy link

melvin-bot bot commented Nov 12, 2024

Triggered auto assignment to @garrettmknight (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@Julesssss
Copy link
Contributor

Sorry @aimane-chnaif, we never had a member of the Bug Zero team assigned so this was missed!

@garrettmknight could you please pay out @aimane-chnaif for C+ review of this PR. Thanks!

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Nov 12, 2024
Copy link

melvin-bot bot commented Nov 12, 2024

📣 @aimane-chnaif 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻
Keep in mind: Code of Conduct | Contributing 📖

@melvin-bot melvin-bot bot added the Overdue label Nov 15, 2024
@garrettmknight
Copy link
Contributor

@aimane-chnaif mind accepting that offer?

@melvin-bot melvin-bot bot added Overdue and removed Overdue labels Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Overdue
Projects
None yet
Development

No branches or pull requests

8 participants