Repository navigation
[eas-cli] Keep the branch name in workflow:run --ref
#4355
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,6 +91,62 @@ export function resolveWorkflowRunSshInput({ | |
| return ssh ? { idleTimeoutSeconds } : null; | ||
| } | ||
|
|
||
| const PASSTHROUGH_REF_PREFIXES = ['refs/heads/', 'refs/tags/']; | ||
|
|
||
| /** | ||
| * Pick the value to send as `gitRef` when running a workflow from `--ref`. | ||
| * | ||
| * The server resolves the ref itself and records it as the run's `requestedGitRef`, | ||
| * which is what the website shows in the "Branch" column and offers in the Git branch | ||
| * filter. Resolving the ref to a commit locally before dispatching therefore throws | ||
| * away the branch or tag name the user asked for. | ||
| * | ||
| * Branch and tag names are passed through untouched, whether they are given in short | ||
| * (`my-branch`) or fully qualified (`refs/heads/my-branch`) form. Everything else keeps | ||
| * being sent as the locally resolved commit, because it either has no meaning in the | ||
| * remote repository or does not mean the same thing there: `HEAD` and `@` resolve to the | ||
| * default branch server-side, revision expressions such as `HEAD~2` are not refs at all, | ||
| * and remote-tracking refs like `origin/my-branch` are local names for remote branches. | ||
| */ | ||
| export function resolveWorkflowRunGitRef({ | ||
| requestedRef, | ||
| symbolicFullName, | ||
| commitSha, | ||
| }: { | ||
| requestedRef: string; | ||
| symbolicFullName: string | null; | ||
| commitSha: string; | ||
| }): string { | ||
| const prefix = PASSTHROUGH_REF_PREFIXES.find(candidate => | ||
| symbolicFullName?.startsWith(candidate) | ||
| ); | ||
| if (!symbolicFullName || !prefix) { | ||
| return commitSha; | ||
| } | ||
| const shortName = symbolicFullName.slice(prefix.length); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a tag and a branch have the same name (for example |
||
| return requestedRef === shortName || requestedRef === symbolicFullName ? requestedRef : commitSha; | ||
| } | ||
|
|
||
| /** | ||
| * Full ref name (e.g. `refs/heads/my-branch`) that `ref` points at, or null when it does | ||
| * not name a ref (a commit hash, a revision expression, or a detached `HEAD`). | ||
| */ | ||
| async function maybeResolveSymbolicFullNameAsync( | ||
| ref: string, | ||
| projectDir: string | ||
| ): Promise<string | null> { | ||
| try { | ||
| const { output } = await spawnAsync( | ||
| 'git', | ||
| ['rev-parse', '--symbolic-full-name', '--verify', ref], | ||
| { cwd: projectDir } | ||
| ); | ||
| return output[0].trim() || null; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| export default class WorkflowRun extends EasCommand { | ||
| static override description = | ||
| 'run an EAS workflow. The entire local project directory will be packaged and uploaded to EAS servers for the workflow run, unless the --ref flag is used.'; | ||
|
|
@@ -184,15 +240,26 @@ export default class WorkflowRun extends EasCommand { | |
| // Run from git ref | ||
| const fileName = path.basename(args.file); | ||
| // Find the real commit, make sure the ref is valid | ||
| gitRef = ( | ||
| const commitSha = ( | ||
| await spawnAsync('git', ['rev-parse', flags.ref], { | ||
| cwd: projectDir, | ||
| }) | ||
| ).output[0].trim(); | ||
| if (!gitRef) { | ||
| if (!commitSha) { | ||
| throw new Error('Failed to resolve git reference'); | ||
| } | ||
| Log.log(`Using workflow file ${fileName} at ${gitRef}`); | ||
| // Send the branch or tag name the user asked for, so that the server records it as | ||
| // the run's requested git ref instead of a bare commit hash. | ||
| gitRef = resolveWorkflowRunGitRef({ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When the CLI sends the branch name, the server uses the latest commit of the branch on the remote, not the local commit. If the local branch has commits that are not pushed, or tracks a remote branch with a different name, the run uses a different commit and the user gets no warning. Before this change, the CLI sent the local SHA, so the run used that exact commit or failed with a clear "commit not found" error. This also goes against the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The server now resolves the branch name 2 times: once in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Possible alternative: |
||
| requestedRef: flags.ref, | ||
| symbolicFullName: await maybeResolveSymbolicFullNameAsync(flags.ref, projectDir), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this starts a second |
||
| commitSha, | ||
| }); | ||
| Log.log( | ||
| gitRef === commitSha | ||
| ? `Using workflow file ${fileName} at ${gitRef}` | ||
| : `Using workflow file ${fileName} at ${gitRef} (${commitSha})` | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line shows the local SHA, but the server resolves the branch name on its own. If the user has commits that are not pushed, the run uses a different SHA than the one shown here. This can confuse the user when they debug a run. |
||
| ); | ||
| let revisionResult: WorkflowRevision | undefined; | ||
| try { | ||
| revisionResult = await WorkflowRevisionMutation.getOrCreateWorkflowRevisionFromGitRefAsync( | ||
|
|
||
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.
On a filesystem that ignores case (the macOS default),
--ref My-Branchcan resolve to the loose ref formy-branch, and--symbolic-full-namethen returnsrefs/heads/My-Branch. That matchesrequestedRef, so the CLI sendsMy-Branch. GitHub ref names are case-sensitive, so the run fails. Before this change, the CLI sent the SHA and this input worked.