mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-14 10:08:06 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
254c3986ce | ||
|
|
49a2bbb1ab | ||
|
|
016923d0ac | ||
|
|
aa2cbb2357 |
No files matched your search
@@ -8,6 +8,7 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- [eas-cli] Include Git commit, commit message, and branch or tag metadata when creating simulator sessions. ([#4071](https://github.com/expo/eas-cli/pull/4071) by [@szdziedzic](https://github.com/szdziedzic))
|
||||
- [build-tools] Collect and upload Argent tool-server session events during remote simulator sessions, mirroring agent-device event collection. ([#4067](https://github.com/expo/eas-cli/pull/4067) by [@szdziedzic](https://github.com/szdziedzic))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
loadSimulatorEnvAsync,
|
||||
resetSimulatorEnvAsync,
|
||||
} from '../../../simulator/env';
|
||||
import { Client } from '../../../vcs/vcs';
|
||||
import SimulatorStart from '../start';
|
||||
|
||||
jest.mock('fs-extra');
|
||||
@@ -74,6 +75,14 @@ const mockLoadSimulatorEnvAsync = jest.mocked(loadSimulatorEnvAsync);
|
||||
const mockResetSimulatorEnvAsync = jest.mocked(resetSimulatorEnvAsync);
|
||||
const mockOra = jest.mocked(ora);
|
||||
const mockPromptAsync = jest.mocked(promptAsync);
|
||||
const vcsClient = {
|
||||
getCommitHashAsync: jest.fn(),
|
||||
getLastCommitMessageAsync: jest.fn(),
|
||||
getCurrentRefAsync: jest.fn(),
|
||||
} as unknown as Client;
|
||||
const mockGetCommitHashAsync = jest.mocked(vcsClient.getCommitHashAsync);
|
||||
const mockGetLastCommitMessageAsync = jest.mocked(vcsClient.getLastCommitMessageAsync);
|
||||
const mockGetCurrentRefAsync = jest.mocked(vcsClient.getCurrentRefAsync);
|
||||
|
||||
function makeCreatedDeviceRunSession(
|
||||
overrides: Partial<CreatedDeviceRunSession> = {}
|
||||
@@ -150,6 +159,9 @@ describe(SimulatorStart, () => {
|
||||
mockLoadSimulatorEnvAsync.mockResolvedValue();
|
||||
mockResetSimulatorEnvAsync.mockResolvedValue();
|
||||
jest.mocked(fs.writeFile).mockResolvedValue(undefined as never);
|
||||
mockGetCommitHashAsync.mockResolvedValue('0123456789abcdef0123456789abcdef01234567');
|
||||
mockGetLastCommitMessageAsync.mockResolvedValue('Show Git context for simulator sessions');
|
||||
mockGetCurrentRefAsync.mockResolvedValue('refs/heads/main');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -170,6 +182,7 @@ describe(SimulatorStart, () => {
|
||||
loggedIn: { graphqlClient },
|
||||
projectDir,
|
||||
projectId: 'project-123',
|
||||
vcsClient,
|
||||
});
|
||||
return { command, getContextAsync };
|
||||
}
|
||||
@@ -189,6 +202,9 @@ describe(SimulatorStart, () => {
|
||||
});
|
||||
expect(mockCreateDeviceRunSessionAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: 'project-123',
|
||||
gitCommitHash: '0123456789abcdef0123456789abcdef01234567',
|
||||
gitCommitMessage: 'Show Git context for simulator sessions',
|
||||
gitRef: 'refs/heads/main',
|
||||
packageVersion: undefined,
|
||||
platform: AppPlatform.Ios,
|
||||
type: DeviceRunSessionType.AgentDevice,
|
||||
@@ -278,6 +294,9 @@ describe(SimulatorStart, () => {
|
||||
);
|
||||
expect(mockCreateDeviceRunSessionAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: 'project-123',
|
||||
gitCommitHash: '0123456789abcdef0123456789abcdef01234567',
|
||||
gitCommitMessage: 'Show Git context for simulator sessions',
|
||||
gitRef: 'refs/heads/main',
|
||||
packageVersion: undefined,
|
||||
platform: AppPlatform.Ios,
|
||||
type: DeviceRunSessionType.AgentDevice,
|
||||
@@ -297,6 +316,9 @@ describe(SimulatorStart, () => {
|
||||
);
|
||||
expect(mockCreateDeviceRunSessionAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: 'project-123',
|
||||
gitCommitHash: '0123456789abcdef0123456789abcdef01234567',
|
||||
gitCommitMessage: 'Show Git context for simulator sessions',
|
||||
gitRef: 'refs/heads/main',
|
||||
packageVersion: undefined,
|
||||
platform: AppPlatform.Ios,
|
||||
type: DeviceRunSessionType.AgentDevice,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
import { truncateGitCommitMessage } from '../../build/metadata';
|
||||
import { getDeviceRunSessionUrl } from '../../build/utils/url';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
@@ -93,6 +94,7 @@ export default class SimulatorStart extends EasCommand {
|
||||
...this.ContextOptions.ProjectId,
|
||||
...this.ContextOptions.ProjectDir,
|
||||
...this.ContextOptions.LoggedIn,
|
||||
...this.ContextOptions.Vcs,
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
@@ -106,6 +108,7 @@ export default class SimulatorStart extends EasCommand {
|
||||
const {
|
||||
projectId,
|
||||
projectDir,
|
||||
vcsClient,
|
||||
loggedIn: { graphqlClient },
|
||||
} = await this.getContextAsync(SimulatorStart, {
|
||||
nonInteractive,
|
||||
@@ -120,6 +123,12 @@ export default class SimulatorStart extends EasCommand {
|
||||
}
|
||||
|
||||
const platform = await resolvePlatformAsync(flags.platform, nonInteractive);
|
||||
const [gitCommitHash, lastCommitMessage, gitRef] = await Promise.all([
|
||||
vcsClient.getCommitHashAsync(),
|
||||
vcsClient.getLastCommitMessageAsync(),
|
||||
vcsClient.getCurrentRefAsync(),
|
||||
]);
|
||||
const gitCommitMessage = truncateGitCommitMessage(lastCommitMessage ?? undefined) ?? null;
|
||||
|
||||
if (existingDeviceRunSessionId) {
|
||||
Log.warn(
|
||||
@@ -140,6 +149,9 @@ export default class SimulatorStart extends EasCommand {
|
||||
type: DEVICE_RUN_SESSION_TYPE_BY_FLAG_VALUE[flags.type],
|
||||
packageVersion: flags['package-version'],
|
||||
maxRunTimeMinutes: flags['max-duration-minutes'],
|
||||
gitCommitHash,
|
||||
gitCommitMessage,
|
||||
gitRef,
|
||||
});
|
||||
deviceRunSessionId = session.id;
|
||||
nullthrows(session.turtleJobRun?.id, 'Expected simulator session to start');
|
||||
|
||||
@@ -10,10 +10,16 @@ import {
|
||||
EnsureDeviceRunSessionStoppedMutationVariables,
|
||||
} from '../generated';
|
||||
|
||||
type CreateDeviceRunSessionInputWithGitContext = CreateDeviceRunSessionInput & {
|
||||
gitCommitHash?: string | null;
|
||||
gitCommitMessage?: string | null;
|
||||
gitRef?: string | null;
|
||||
};
|
||||
|
||||
export const DeviceRunSessionMutation = {
|
||||
async createDeviceRunSessionAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
deviceRunSessionInput: CreateDeviceRunSessionInput
|
||||
deviceRunSessionInput: CreateDeviceRunSessionInputWithGitContext
|
||||
): Promise<CreateDeviceRunSessionMutation['deviceRunSession']['createDeviceRunSession']> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
|
||||
@@ -243,6 +243,47 @@ describe('git', () => {
|
||||
).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
describe('getCurrentRefAsync', () => {
|
||||
let repoRoot: string;
|
||||
let vcs: GitClient;
|
||||
|
||||
beforeAll(async () => {
|
||||
repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-ref-test-'));
|
||||
await spawnAsync('git', ['init'], { cwd: repoRoot });
|
||||
await spawnAsync('git', ['checkout', '-b', 'feature/device-sessions'], { cwd: repoRoot });
|
||||
await spawnAsync('git', ['commit', '--allow-empty', '-m', 'initial commit'], {
|
||||
cwd: repoRoot,
|
||||
});
|
||||
vcs = new GitClient({
|
||||
requireCommit: false,
|
||||
maybeCwdOverride: repoRoot,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(repoRoot, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('returns a fully qualified branch ref', async () => {
|
||||
await expect(vcs.getCurrentRefAsync()).resolves.toBe('refs/heads/feature/device-sessions');
|
||||
});
|
||||
|
||||
it('returns a fully qualified tag ref for a detached checkout', async () => {
|
||||
await spawnAsync('git', ['tag', 'v1.2.3'], { cwd: repoRoot });
|
||||
await spawnAsync('git', ['checkout', '--detach', 'v1.2.3'], { cwd: repoRoot });
|
||||
|
||||
await expect(vcs.getCurrentRefAsync()).resolves.toBe('refs/tags/v1.2.3');
|
||||
});
|
||||
|
||||
it('returns null for a detached checkout without an exact tag', async () => {
|
||||
await spawnAsync('git', ['commit', '--allow-empty', '-m', 'detached commit'], {
|
||||
cwd: repoRoot,
|
||||
});
|
||||
|
||||
await expect(vcs.getCurrentRefAsync()).resolves.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when requireCommit is true', () => {
|
||||
it('adheres to .easignore', async () => {
|
||||
const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
|
||||
|
||||
@@ -310,6 +310,30 @@ export default class GitClient extends Client {
|
||||
}
|
||||
}
|
||||
|
||||
public override async getCurrentRefAsync(): Promise<string | null> {
|
||||
try {
|
||||
const branchRef = (
|
||||
await spawnAsync('git', ['symbolic-ref', '--quiet', 'HEAD'], {
|
||||
cwd: this.maybeCwdOverride,
|
||||
})
|
||||
).stdout.trim();
|
||||
if (branchRef) {
|
||||
return branchRef;
|
||||
}
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
const tag = (
|
||||
await spawnAsync('git', ['describe', '--tags', '--exact-match', 'HEAD'], {
|
||||
cwd: this.maybeCwdOverride,
|
||||
})
|
||||
).stdout.trim();
|
||||
return tag ? `refs/tags/${tag}` : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override async getLastCommitMessageAsync(): Promise<string | null> {
|
||||
try {
|
||||
return (
|
||||
|
||||
@@ -66,6 +66,12 @@ export abstract class Client {
|
||||
return null;
|
||||
}
|
||||
|
||||
// (optional) returns the fully qualified ref for the current checkout
|
||||
// used for metadata - implementation can be safely skipped
|
||||
public async getCurrentRefAsync(): Promise<string | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
// (optional) returns message of the last commit
|
||||
// used for EAS Update - implementation can be safely skipped
|
||||
public async getLastCommitMessageAsync(): Promise<string | null> {
|
||||
|
||||
Reference in new issue
Block a user