-
Notifications
You must be signed in to change notification settings - Fork 98
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
[eas-cli] [ENG-11026] Add build:delete command #2178
[eas-cli] [ENG-11026] Add build:delete command #2178
Conversation
Added a new command build:delete. Shares some code with build:cancel, so I have moved the redundancies to a utils file at src/commandUtils/builds See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Added a test file based on existing tests for build:cancel command. Adding more tests See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Size Change: +5.42 kB (0%) Total Size: 55.5 MB
|
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #2178 +/- ##
==========================================
+ Coverage 54.23% 54.24% +0.02%
==========================================
Files 509 511 +2
Lines 18660 18756 +96
Branches 3737 3758 +21
==========================================
+ Hits 10118 10173 +55
- Misses 8521 8562 +41
Partials 21 21 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool!
limit: 10, | ||
filter: { status }, | ||
}); | ||
builds.push(...buildsForStatus); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we order them by createdAt
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they are sorted like that implicitly, but need to double check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They were, but it fell apart when combining results for different statuses, as this would group the builds by status too. Added explicit sorting before returning
graphqlClient: ExpoGraphqlClient, | ||
projectId: string, | ||
statuses?: BuildStatus[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use a { graphqlClient, projectId, statuses }
argument. This way, if we add more filters (like platform: Platform[]
) it's much easier and readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
throw error; | ||
} | ||
if (builds.length === 0) { | ||
Log.warn(`There aren't any builds for the project ${projectDisplayName}.`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log.warn(`There aren't any builds for the project ${projectDisplayName}.`); | |
Log.warn(`There are no builds for the project ${projectDisplayName}.`); |
Or maybe something like "we couldn't find any builds"? I think it feels more human?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message was copied from an existing command, but I can update both 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
let buildId: string | null = buildIdFromArg; | ||
if (!buildId) { | ||
if (nonInteractive) { | ||
throw new Error('BUILD_ID must not be empty in non-interactive mode'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do users know the argument is called BUILD_ID
? If not, maybe we should changes this to say "The build ID argument"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks really good 🙌
const buildsForStatus = await BuildQuery.viewBuildsOnAppAsync(graphqlClient, { | ||
appId: projectId, | ||
offset: 0, | ||
limit: 10, | ||
filter: { status }, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just create promises here and await them all using Promise.all
to make it faster, instead of executing it sequentially?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's so obvious, and yet I always forget about that 😬
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
export default class BuildDelete extends EasCommand { | ||
static override description = 'delete a build'; | ||
static override args = [{ name: 'BUILD_ID' }]; | ||
static override flags = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can allow users to filter by platform and profile as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WDYM? If they provide platform to delete all builds from a platform? That seems rather... prone to human errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I meant, when displaying the list of builds. So the people can decide what filters should be applied to this list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the filter flags for platform
and profile
Explicitly sorts fetched builds by descending order of `created_at`. In case multiple results were combined (for different statuses) they would by already sorted, but grouped by status also See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Changed `fetchBuildsAsync` arguments into single object argument for readability See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Changed the message displayed when no builds are found for deletion/cancellation to be more human-like See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Changed the message displayed when no build ID is provided for non-interactive mode, to not include the argument name but rather its description See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Changed for loop with async calls into await promise.all() See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
When not providing an ID of the build to delete, the user can now filter the listed builds by platform and build profile using new flags. The same change has also been applied to `build:cancel` command See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
/changelog-entry new-feature Added |
/changelog-entry new-feature Add filter flags for |
Using imperative form in the changelog See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
…-11026-add-build-delete-command # Conflicts: # CHANGELOG.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I have a few last suggestions 🙌
let builds: BuildFragment[]; | ||
const queryFilters: InputMaybe<BuildFilter> = {}; | ||
if (filters?.platform && filters?.platform !== 'all') { | ||
queryFilters['platform'] = filters?.platform.toUpperCase() as AppPlatform; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about using some mapping from one type to the other type here? By doing this TS will warn us if something type-related changes and it will be more explicit (for example we will see if due to some changes the toUpperCase
isn't enough)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a mapping function the mapping
}); | ||
} else { | ||
builds = ( | ||
await Promise.all( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
platform: Flags.string({ | ||
char: 'p', | ||
description: 'Platform for which to list builds when ID not provided', | ||
options: ['android', 'ios', 'all'], | ||
}), | ||
profile: Flags.string({ | ||
char: 'e', | ||
description: | ||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.', | ||
helpValue: 'PROFILE_NAME', | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably a nitpick, but can we throw an error if the combination of build ID and these flags is provided? I want to avoid any confusion for the users here. What I mean is a situation where users believe this flag will only delete a build with such id if it is of a given platform and profile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a valid point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
export default class BuildCancel extends EasCommand { | ||
static override description = 'cancel a build'; | ||
|
||
static override args = [{ name: 'BUILD_ID' }]; | ||
|
||
static override flags = { | ||
...EASNonInteractiveFlag, | ||
platform: Flags.string({ | ||
char: 'p', | ||
description: 'Platform for which to list builds when ID not provided', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
description: 'Platform for which to list builds when ID not provided', | |
description: 'Filter builds by the platform if BUILD_ID is not provided', |
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
profile: Flags.string({ | ||
char: 'e', | ||
description: | ||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.', | |
'Filter builds by profile if BUILD_ID is not provided', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
Disallow using both the build ID and filter flags when using `build:delete` and `build:cancel` commands See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Updated the descriptions of the filter flags as per suggestion during review See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Added function for mapping platform flag into generated graphQL value See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
function toAppPlatform(platform: string): AppPlatform { | ||
const capitalizedPlatform = (platform[0].toUpperCase() + | ||
platform.substring(1)) as keyof typeof AppPlatform; | ||
return AppPlatform[capitalizedPlatform]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also do
const platformToAppPlatform: Record<string, AppPlatform | undefined> = {
android: AppPlatform.Android,
ios: AppPlatform.Ios,
};
A bit simpler and safer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that
Replaced function with a mapping object See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't kill me, these are the last 3 comments that can allow you to type everything better 🙈
const platformToAppPlatform: Record<string, AppPlatform | undefined> = { | ||
android: AppPlatform.Android, | ||
ios: AppPlatform.Ios, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const platformToAppPlatform: Record<string, AppPlatform | undefined> = { | |
android: AppPlatform.Android, | |
ios: AppPlatform.Ios, | |
}; | |
const platformToAppPlatform: Record< | |
Exclude<RequestedPlatform, RequestedPlatform.All>, | |
AppPlatform | |
> = { | |
[RequestedPlatform.Android]: AppPlatform.Android, | |
[RequestedPlatform.Ios]: AppPlatform.Ios, | |
}; |
platform: Flags.string({ | ||
char: 'p', | ||
description: 'Filter builds by the platform if build ID is not provided', | ||
options: ['android', 'ios', 'all'], | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
platform: Flags.string({ | |
char: 'p', | |
description: 'Filter builds by the platform if build ID is not provided', | |
options: ['android', 'ios', 'all'], | |
}), | |
platform: Flags.enum({ | |
char: 'p', | |
description: 'Filter builds by the platform if build ID is not provided', | |
options: Object.values(RequestedPlatform), | |
}), |
if (buildIdFromArg && (platform || profile)) { | ||
throw new Error( | ||
'Build ID cannot be used together with platform and profile flags. They are used to filter the list of builds when not providing the build ID' | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
platform: Flags.string({ | ||
char: 'p', | ||
description: 'Filter builds by the platform if build ID is not provided', | ||
options: ['android', 'ios', 'all'], | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
platform: Flags.string({ | |
char: 'p', | |
description: 'Filter builds by the platform if build ID is not provided', | |
options: ['android', 'ios', 'all'], | |
}), | |
platform: Flags.enum({ | |
char: 'p', | |
description: 'Filter builds by the platform if build ID is not provided', | |
options: Object.values(RequestedPlatform), | |
}), |
Replaced strings with object enums See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
Removed undefined See: https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
✅ Thank you for adding the changelog entry! |
Why
https://linear.app/expo/issue/ENG-11026/add-eas-builddelete-command
How
Added a new
build:delete
command. It shares some similarities withbuild:cancel
command, can be used with build id provided or prompt the user for id if not (not available in non-interactive mode). The difference is thatbuild:cancel
has restrictions on build status, andbuild:delete
does not. The shared code has been extracted to a helper file undersrc/commandUtils
. Additionally, 2 filter flags has been added for the case when the user does not provide the ID of the build to be deleted and a list of builds is printed, it can be filtered byplatform
and/orprofile
. The same has been applied tobuild:cancel
as wellScreens
With build id
1


2
With prompt
1



2
3
Non-interactive with id
1

Non-interactive with prompt (not allowed)
1

New filter flags
No flags
build:delete
withplatform/p
flag1


2
build:delete
withprofile/e
flag1


2
Same for
build:cancel
command1



2
3
Using both build ID and filter flags is not allowed
1


2
Test Plan
Added tests similar to those for
build:cancel
Tested manually
Deployment Plan
No dependency on other services, just release a new version of CLI when needed