Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/commands/cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import {
CompatibilityData,
fetchCompatibilityData,
} from '../utils/compatibility.js';
import { renderNotices } from '../services/notices.service.js';
import { platformFromAppFile, renderNotices } from '../services/notices.service.js';
import { resolveApiUrl } from '../utils/config-store.js';
import { downloadExpoUrl, extractTarGz, findAppBundle, isUrl } from '../utils/expo.js';
import {
Expand Down Expand Up @@ -494,17 +494,32 @@ export const cloudCommand = defineCommand({
// returned with the compatibility data. Replaces the previously hardcoded
// iOS-16 deprecation warning — that is now a seeded notice gated on the
// selected iOS version below. Honours --json via out/warnOut.
renderNotices(
const visibleNotices = renderNotices(
compatibilityData.notices,
{
platform: platformFromAppFile(finalAppFile),
ios_version: iOSVersion,
ios_device: iOSDevice,
android_api_level: androidApiLevel,
android_device: androidDevice,
// Resolved (what the run will use) and requested (undefined when the
// customer relied on the default), so a notice can target either.
maestro_version: resolvedMaestroVersion,
requested_maestro_version: maestroVersion,
cli_version: cliVersion,
ci_provider: ciContext.provider,
ci_wrapper_version: ciContext.wrapperVersion,
},
{ out },
);
// --json suppresses the rendered lines, so the payload carries them instead.
const noticesForJson = visibleNotices.map((n) => ({
slug: n.slug,
level: n.level,
title: n.title,
body: n.body,
learnMoreUrl: n.learnMoreUrl,
}));

deviceValidationService.validateAndroidDevice(
androidApiLevel,
Expand Down Expand Up @@ -963,6 +978,7 @@ export const cloudCommand = defineCommand({
tags: testMetadataMap[r.test_file_name]?.tags || [],
})),
uploadId: results[0].test_upload_id,
notices: noticesForJson,
};

if (jsonFileFlag) {
Expand Down Expand Up @@ -1087,7 +1103,7 @@ export const cloudCommand = defineCommand({
});
}

const jsonOutput = pollingResult;
const jsonOutput = { ...pollingResult, notices: noticesForJson };
if (jsonFileFlag) {
const jsonFilePath = jsonFileName || `${results[0].test_upload_id}_dcd.json`;
writeJSONFile(jsonFilePath, jsonOutput, {
Expand Down
15 changes: 15 additions & 0 deletions src/services/notices.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ function renderNotice(notice: Notice, opts: RenderNoticesOptions): void {
* payload instead of printing. `opts.out` is the caller's `--json`-gated
* emitter, so under `--json` nothing prints but the list is still returned.
*/
/**
* Best-effort platform from the app artifact's extension, so a notice can be
* targeted at one platform (e.g. "you rely on the default Android API level")
* without firing on the other platform's runs.
*/
export function platformFromAppFile(
appFile: string | undefined,
): 'android' | 'ios' | undefined {
if (!appFile) return undefined;
const ext = appFile.split('?')[0].toLowerCase().match(/.([a-z0-9]+)$/)?.[1];
if (ext === 'apk' || ext === 'aab') return 'android';
if (ext === 'zip' || ext === 'app' || ext === 'ipa') return 'ios';
return undefined;
}

export function renderNotices(
notices: Notice[] | undefined,
ctx: NoticeContext,
Expand Down
Loading