screenci 0.0.24 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Dockerfile +10 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +232 -59
- package/dist/cli.js.map +1 -1
- package/dist/src/changeFocus.d.ts.map +1 -1
- package/dist/src/changeFocus.js +15 -3
- package/dist/src/changeFocus.js.map +1 -1
- package/dist/src/cue.d.ts +8 -6
- package/dist/src/cue.d.ts.map +1 -1
- package/dist/src/cue.js +11 -0
- package/dist/src/cue.js.map +1 -1
- package/dist/src/defaults.d.ts +4 -0
- package/dist/src/defaults.d.ts.map +1 -1
- package/dist/src/defaults.js +4 -0
- package/dist/src/defaults.js.map +1 -1
- package/dist/src/events.d.ts +6 -6
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/hide.js +1 -1
- package/dist/src/hide.js.map +1 -1
- package/dist/src/instrument.d.ts.map +1 -1
- package/dist/src/instrument.js +26 -9
- package/dist/src/instrument.js.map +1 -1
- package/dist/src/mouse.d.ts +1 -0
- package/dist/src/mouse.d.ts.map +1 -1
- package/dist/src/mouse.js +15 -6
- package/dist/src/mouse.js.map +1 -1
- package/dist/src/video.d.ts.map +1 -1
- package/dist/src/video.js +3 -3
- package/dist/src/video.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/skills/screenci/SKILL.md +10 -7
package/dist/Dockerfile
CHANGED
|
@@ -10,15 +10,23 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
10
10
|
&& rm -rf /var/lib/apt/lists/*
|
|
11
11
|
|
|
12
12
|
# ── Dependency layer (cached until package.json changes) ──────────────────────
|
|
13
|
-
# Install
|
|
13
|
+
# Install through a workspace to keep dependency resolution unchanged, then
|
|
14
|
+
# replace the workspace symlink with a real package under node_modules. Playwright
|
|
15
|
+
# skips transforms for node_modules packages, but follows workspace symlinks to
|
|
16
|
+
# /app/screenci and can rewrite compiled ESM as CJS while loading TS configs.
|
|
14
17
|
COPY package.json ./screenci/
|
|
15
|
-
RUN printf '{"private":true,"workspaces":["screenci"]}' > package.json &&
|
|
18
|
+
RUN printf '{"private":true,"workspaces":["screenci"]}' > package.json && \
|
|
19
|
+
npm install && \
|
|
20
|
+
rm /app/node_modules/screenci && \
|
|
21
|
+
mkdir -p /app/node_modules/screenci
|
|
16
22
|
|
|
17
23
|
# Playwright browser download: only re-runs when the playwright version changes.
|
|
18
24
|
RUN npx playwright install chromium --with-deps
|
|
19
25
|
|
|
20
26
|
# ── screenci build output ─────────────────────────────────────────────────────
|
|
21
27
|
COPY dist ./screenci/dist/
|
|
28
|
+
COPY package.json ./node_modules/screenci/package.json
|
|
29
|
+
COPY dist ./node_modules/screenci/dist/
|
|
22
30
|
|
|
23
31
|
# Explicit bin wrapper — no npm bin-linking magic needed.
|
|
24
32
|
RUN printf '#!/bin/sh\nexec node /app/screenci/dist/cli.js "$@"\n' > /app/node_modules/.bin/screenci && \
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AA4D/C,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAiBD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,EACtD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GACxC,MAAM,IAAI,CAiBZ;AAuED,QAAA,MAAM,mCAAmC;;;CAG/B,CAAA;AAEV,KAAK,oBAAoB,GAAG,MAAM,OAAO,mCAAmC,CAAA;AAmc5E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,GAAG,uBAAuB,GACxC,QAAQ,GAAG,uBAAuB,CAKpC;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,aAAa,CAqEf;AAQD,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,MAAM,CAeR;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CAcN;AAgRD,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AA0FD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GAAG,SAAS,GAClC,MAAM,GAAG,SAAS,CAepB;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AA4D/C,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAiBD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,EACtD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GACxC,MAAM,IAAI,CAiBZ;AAuED,QAAA,MAAM,mCAAmC;;;CAG/B,CAAA;AAEV,KAAK,oBAAoB,GAAG,MAAM,OAAO,mCAAmC,CAAA;AAmc5E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,GAAG,uBAAuB,GACxC,QAAQ,GAAG,uBAAuB,CAKpC;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,aAAa,CAqEf;AAQD,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,MAAM,CAeR;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CAcN;AAgRD,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AA0FD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GAAG,SAAS,GAClC,MAAM,GAAG,SAAS,CAepB;AAuvBD,wBAAsB,IAAI,kBAoQzB;AAoJD,wBAAgB,sBAAsB,CACpC,aAAa,CAAC,EAAE,oBAAoB,GACnC,oBAAoB,CAoBtB"}
|
package/dist/cli.js
CHANGED
|
@@ -982,11 +982,10 @@ export default defineConfig({
|
|
|
982
982
|
})
|
|
983
983
|
`;
|
|
984
984
|
}
|
|
985
|
-
function generatePackageJson(projectName, includePlaywrightCli = false) {
|
|
985
|
+
function generatePackageJson(projectName, includePlaywrightCli = false, screenciDependency = 'latest') {
|
|
986
986
|
const npmName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
987
987
|
const devDependencies = {
|
|
988
988
|
'@types/node': '^25.0.0',
|
|
989
|
-
tsx: '^4.21.0',
|
|
990
989
|
};
|
|
991
990
|
if (includePlaywrightCli) {
|
|
992
991
|
devDependencies['@playwright/cli'] = 'latest';
|
|
@@ -1002,7 +1001,7 @@ function generatePackageJson(projectName, includePlaywrightCli = false) {
|
|
|
1002
1001
|
test: 'screenci test',
|
|
1003
1002
|
},
|
|
1004
1003
|
dependencies: {
|
|
1005
|
-
screenci:
|
|
1004
|
+
screenci: screenciDependency,
|
|
1006
1005
|
},
|
|
1007
1006
|
devDependencies,
|
|
1008
1007
|
}, null, 2) + '\n');
|
|
@@ -1020,13 +1019,17 @@ Learn more: https://screenci.com/docs/intro/
|
|
|
1020
1019
|
|
|
1021
1020
|
## Quick start
|
|
1022
1021
|
|
|
1023
|
-
1.
|
|
1022
|
+
1. Create your own videos in \`videos/*.video.ts\`, either manually or with an AI agent using your source code or a URL.
|
|
1024
1023
|
|
|
1025
|
-
|
|
1024
|
+
2. Run videos locally to test the script working:
|
|
1026
1025
|
|
|
1027
|
-
|
|
1026
|
+
\`npx screenci test\` or with UI mode: \`npx screenci test --ui\`
|
|
1027
|
+
|
|
1028
|
+
3. Record videos:
|
|
1028
1029
|
|
|
1029
1030
|
\`npx screenci record\`
|
|
1031
|
+
|
|
1032
|
+
4. View results on screenci.com and optionally enable a public URL to embed the video on your site.
|
|
1030
1033
|
`;
|
|
1031
1034
|
}
|
|
1032
1035
|
function generateDockerfile() {
|
|
@@ -1062,25 +1065,23 @@ jobs:
|
|
|
1062
1065
|
SCREENCI_SECRET: \${{ secrets.SCREENCI_SECRET }}
|
|
1063
1066
|
run: |
|
|
1064
1067
|
if [ -z "$SCREENCI_SECRET" ]; then
|
|
1065
|
-
echo "::error::SCREENCI_SECRET is not set.
|
|
1068
|
+
echo "::error::SCREENCI_SECRET is not set. Copy it from https://app.screenci.com/secrets and add it under Settings → Secrets and variables → Actions → Repository secrets."
|
|
1066
1069
|
exit 1
|
|
1067
1070
|
fi
|
|
1068
1071
|
|
|
1069
1072
|
- uses: actions/checkout@v4
|
|
1070
1073
|
|
|
1071
|
-
-
|
|
1072
|
-
|
|
1074
|
+
- uses: actions/setup-node@v6
|
|
1075
|
+
with:
|
|
1076
|
+
node-version: latest
|
|
1077
|
+
|
|
1078
|
+
- name: Install dependencies
|
|
1079
|
+
run: npm install
|
|
1073
1080
|
|
|
1074
1081
|
- name: Record
|
|
1075
1082
|
env:
|
|
1076
1083
|
SCREENCI_SECRET: \${{ secrets.SCREENCI_SECRET }}
|
|
1077
|
-
run:
|
|
1078
|
-
docker run --rm \\
|
|
1079
|
-
-e SCREENCI_SECRET \\
|
|
1080
|
-
-e SCREENCI_IN_CONTAINER=true \\
|
|
1081
|
-
-e SCREENCI_RECORD=true \\
|
|
1082
|
-
screenci-project \\
|
|
1083
|
-
npm run record
|
|
1084
|
+
run: npm run record
|
|
1084
1085
|
`;
|
|
1085
1086
|
}
|
|
1086
1087
|
function openBrowser(url) {
|
|
@@ -1134,23 +1135,110 @@ async function performBrowserLogin(appUrl) {
|
|
|
1134
1135
|
});
|
|
1135
1136
|
}
|
|
1136
1137
|
function generateExampleVideo() {
|
|
1137
|
-
return `import { video } from 'screenci'
|
|
1138
|
+
return `import { createNarration, hide, video, voices } from 'screenci'
|
|
1139
|
+
|
|
1140
|
+
const narration = createNarration({
|
|
1141
|
+
voice: { name: voices.Sophie, style: 'Clear, friendly product walkthrough' },
|
|
1142
|
+
languages: {
|
|
1143
|
+
en: {
|
|
1144
|
+
cues: {
|
|
1145
|
+
intro:
|
|
1146
|
+
'Here is how to find instructions for starting to create your own ScreenCI [pronounce: screen see eye] videos. [short pause] Start on the homepage, then open the documentation from the hero section.',
|
|
1147
|
+
docs: 'The documentation opens with the guide sidebar on the left. In the Guides group, choose AI-Supported Editing.',
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
es: {
|
|
1151
|
+
cues: {
|
|
1152
|
+
intro:
|
|
1153
|
+
'Aqui se muestra como encontrar instrucciones para empezar a crear tus propios videos de ScreenCI [pronounce: screen see eye]. [short pause] Comienza en la pagina principal y abre la documentacion desde la seccion principal.',
|
|
1154
|
+
docs: 'La documentacion se abre con la barra lateral de guias a la izquierda. En el grupo Guias, elige Edicion asistida por IA.',
|
|
1155
|
+
},
|
|
1156
|
+
},
|
|
1157
|
+
},
|
|
1158
|
+
})
|
|
1138
1159
|
|
|
1139
|
-
video('
|
|
1140
|
-
await
|
|
1141
|
-
|
|
1160
|
+
video('Navigate to AI editing documentation', async ({ page }) => {
|
|
1161
|
+
await hide(async () => {
|
|
1162
|
+
await page.goto('https://screenci.com/')
|
|
1163
|
+
await page.getByText('ScreenCI', { exact: true }).first().waitFor()
|
|
1164
|
+
})
|
|
1165
|
+
|
|
1166
|
+
await narration.intro
|
|
1167
|
+
await page.getByRole('link', { name: 'View Documentation' }).click()
|
|
1168
|
+
|
|
1169
|
+
await narration.docs
|
|
1170
|
+
await page
|
|
1171
|
+
.getByRole('link', { name: 'AI-Supported Editing', exact: true })
|
|
1172
|
+
.click()
|
|
1142
1173
|
})
|
|
1143
1174
|
`;
|
|
1144
1175
|
}
|
|
1145
1176
|
async function promptProjectName() {
|
|
1146
1177
|
return input({ message: 'Project name:' });
|
|
1147
1178
|
}
|
|
1179
|
+
async function promptInitGitRepository() {
|
|
1180
|
+
return confirm({
|
|
1181
|
+
message: 'Initialize a git repository? (Y/n)',
|
|
1182
|
+
default: true,
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
async function promptInitDependencies() {
|
|
1186
|
+
return confirm({
|
|
1187
|
+
message: 'Install dependencies now, including Chromium for Playwright? (Y/n)',
|
|
1188
|
+
default: true,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
async function promptInitAiAuthoring() {
|
|
1192
|
+
return confirm({
|
|
1193
|
+
message: 'Do you want to write videos with an AI agent based on a URL and not just source code? If yes, playwright-cli will be also installed.',
|
|
1194
|
+
default: true,
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
async function promptInitGithubActionCi() {
|
|
1198
|
+
return confirm({
|
|
1199
|
+
message: 'Do you want to add Github Action CI? (Y/n)',
|
|
1200
|
+
default: true,
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1148
1203
|
function getProjectDirName(name) {
|
|
1149
1204
|
return name.toLowerCase().replace(/\s+/g, '-');
|
|
1150
1205
|
}
|
|
1151
1206
|
function getInitProjectRoot() {
|
|
1152
1207
|
return process.env['SCREENCI_INIT_CWD'] ?? process.cwd();
|
|
1153
1208
|
}
|
|
1209
|
+
function isSourceCliEntrypoint(entrypoint) {
|
|
1210
|
+
return (entrypoint?.endsWith('/cli.ts') === true ||
|
|
1211
|
+
entrypoint?.endsWith('\\cli.ts') === true);
|
|
1212
|
+
}
|
|
1213
|
+
function getDevScreenciPackageRoot() {
|
|
1214
|
+
const explicitRoot = process.env.SCREENCI_DEV_PACKAGE_ROOT?.trim();
|
|
1215
|
+
if (explicitRoot)
|
|
1216
|
+
return resolve(explicitRoot);
|
|
1217
|
+
if (!isSourceCliEntrypoint(process.argv[1]))
|
|
1218
|
+
return undefined;
|
|
1219
|
+
return dirname(fileURLToPath(import.meta.url));
|
|
1220
|
+
}
|
|
1221
|
+
function getLocalScreenciDependency(packageRoot, projectDir) {
|
|
1222
|
+
const relativePath = pathRelative(projectDir, packageRoot) || '.';
|
|
1223
|
+
const normalizedPath = relativePath.replace(/\\/g, '/');
|
|
1224
|
+
return `file:${normalizedPath.startsWith('.') ? normalizedPath : `./${normalizedPath}`}`;
|
|
1225
|
+
}
|
|
1226
|
+
async function buildLocalScreenciPackage(packageRoot) {
|
|
1227
|
+
logger.info(`Using local screenci package: ${packageRoot}`);
|
|
1228
|
+
logger.info("Running 'npm run build' for local screenci package...");
|
|
1229
|
+
await spawnInherited('npm', ['run', 'build'], packageRoot, 'screenci dev build');
|
|
1230
|
+
}
|
|
1231
|
+
async function installLocalScreenciPackage(projectDir, packageRoot) {
|
|
1232
|
+
const packageJsonPath = resolve(projectDir, 'package.json');
|
|
1233
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
1234
|
+
packageJson.dependencies = {
|
|
1235
|
+
...packageJson.dependencies,
|
|
1236
|
+
screenci: getLocalScreenciDependency(packageRoot, projectDir),
|
|
1237
|
+
};
|
|
1238
|
+
await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
1239
|
+
logger.info('Installing local screenci package into this project...');
|
|
1240
|
+
await spawnInherited('npm', ['install', '--install-links'], projectDir, 'screenci dev install');
|
|
1241
|
+
}
|
|
1154
1242
|
function buildChildEnv() {
|
|
1155
1243
|
const { PATH, HOME, USER, LOGNAME, TMPDIR, TEMP, TMP } = process.env;
|
|
1156
1244
|
return {
|
|
@@ -1169,6 +1257,7 @@ function buildChildEnv() {
|
|
|
1169
1257
|
SCREENCI_IN_CONTAINER: process.env.SCREENCI_IN_CONTAINER,
|
|
1170
1258
|
SCREENCI_RECORD: process.env.SCREENCI_RECORD,
|
|
1171
1259
|
SCREENCI_SIGNAL_LOGGING: process.env.SCREENCI_SIGNAL_LOGGING,
|
|
1260
|
+
SCREENCI_DEV_PACKAGE_ROOT: process.env.SCREENCI_DEV_PACKAGE_ROOT,
|
|
1172
1261
|
};
|
|
1173
1262
|
}
|
|
1174
1263
|
function requireContainerRuntime() {
|
|
@@ -1220,7 +1309,8 @@ function checkNodeVersion() {
|
|
|
1220
1309
|
process.exit(1);
|
|
1221
1310
|
}
|
|
1222
1311
|
}
|
|
1223
|
-
async function runInit(projectNameArg,
|
|
1312
|
+
async function runInit(projectNameArg, options) {
|
|
1313
|
+
const { verbose, git, install, yes, skill, ci } = options;
|
|
1224
1314
|
checkNodeVersion();
|
|
1225
1315
|
checkContainerRuntimeForInit();
|
|
1226
1316
|
const initCwd = getInitProjectRoot();
|
|
@@ -1238,10 +1328,26 @@ async function runInit(projectNameArg, verbose = false) {
|
|
|
1238
1328
|
logger.error(`Error: Directory "${dirName}" already exists`);
|
|
1239
1329
|
process.exit(1);
|
|
1240
1330
|
}
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1331
|
+
const shouldInitializeGitRepository = yes
|
|
1332
|
+
? true
|
|
1333
|
+
: git
|
|
1334
|
+
? true
|
|
1335
|
+
: await promptInitGitRepository();
|
|
1336
|
+
const shouldInstallDependencies = yes
|
|
1337
|
+
? true
|
|
1338
|
+
: install
|
|
1339
|
+
? true
|
|
1340
|
+
: await promptInitDependencies();
|
|
1341
|
+
const shouldAddPlaywrightCli = yes
|
|
1342
|
+
? true
|
|
1343
|
+
: skill
|
|
1344
|
+
? true
|
|
1345
|
+
: await promptInitAiAuthoring();
|
|
1346
|
+
const shouldAddGithubActionCi = yes
|
|
1347
|
+
? true
|
|
1348
|
+
: ci
|
|
1349
|
+
? true
|
|
1350
|
+
: await promptInitGithubActionCi();
|
|
1245
1351
|
const skillsArgs = [
|
|
1246
1352
|
'--yes',
|
|
1247
1353
|
'skills',
|
|
@@ -1253,15 +1359,28 @@ async function runInit(projectNameArg, verbose = false) {
|
|
|
1253
1359
|
'-y',
|
|
1254
1360
|
];
|
|
1255
1361
|
const skillsCommand = `npx ${skillsArgs.join(' ')}`;
|
|
1362
|
+
const devScreenciPackageRoot = getDevScreenciPackageRoot();
|
|
1363
|
+
const screenciDependency = devScreenciPackageRoot
|
|
1364
|
+
? getLocalScreenciDependency(devScreenciPackageRoot, projectDir)
|
|
1365
|
+
: 'latest';
|
|
1366
|
+
if (devScreenciPackageRoot) {
|
|
1367
|
+
await buildLocalScreenciPackage(devScreenciPackageRoot);
|
|
1368
|
+
}
|
|
1256
1369
|
await mkdir(resolve(projectDir, 'videos'), { recursive: true });
|
|
1257
|
-
|
|
1370
|
+
if (shouldAddGithubActionCi) {
|
|
1371
|
+
await mkdir(resolve(projectDir, '.github', 'workflows'), {
|
|
1372
|
+
recursive: true,
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1258
1375
|
await writeFile(resolve(projectDir, 'screenci.config.ts'), generateConfig(projectName));
|
|
1259
|
-
await writeFile(resolve(projectDir, 'package.json'), generatePackageJson(dirName, shouldAddPlaywrightCli));
|
|
1376
|
+
await writeFile(resolve(projectDir, 'package.json'), generatePackageJson(dirName, shouldAddPlaywrightCli, screenciDependency));
|
|
1260
1377
|
await writeFile(resolve(projectDir, 'README.md'), generateReadme(projectName));
|
|
1261
1378
|
await writeFile(resolve(projectDir, 'Dockerfile'), generateDockerfile());
|
|
1262
1379
|
await writeFile(resolve(projectDir, '.gitignore'), generateGitignore());
|
|
1263
1380
|
await writeFile(resolve(projectDir, 'videos', 'example.video.ts'), generateExampleVideo());
|
|
1264
|
-
|
|
1381
|
+
if (shouldAddGithubActionCi) {
|
|
1382
|
+
await writeFile(resolve(projectDir, '.github', 'workflows', 'record.yml'), generateGithubAction());
|
|
1383
|
+
}
|
|
1265
1384
|
await writeFile(resolve(projectDir, '.env'), '');
|
|
1266
1385
|
logger.info(`Initialized screenci project "${projectName}" in ${projectDir}/`);
|
|
1267
1386
|
logger.info('Files created:');
|
|
@@ -1271,44 +1390,77 @@ async function runInit(projectNameArg, verbose = false) {
|
|
|
1271
1390
|
logger.info(' Dockerfile');
|
|
1272
1391
|
logger.info(' .gitignore');
|
|
1273
1392
|
logger.info(' videos/example.video.ts');
|
|
1274
|
-
|
|
1393
|
+
if (shouldAddGithubActionCi) {
|
|
1394
|
+
logger.info(' .github/workflows/record.yml');
|
|
1395
|
+
}
|
|
1275
1396
|
logger.info(' .env (empty placeholder)');
|
|
1276
1397
|
logger.info('');
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
}
|
|
1282
|
-
else {
|
|
1283
|
-
const spinner = ora('Adding ScreenCI skills...').start();
|
|
1284
|
-
try {
|
|
1285
|
-
await spawnSilent('npx', skillsArgs, projectDir);
|
|
1286
|
-
spinner.succeed('ScreenCI skills added');
|
|
1398
|
+
if (shouldInitializeGitRepository) {
|
|
1399
|
+
if (verbose) {
|
|
1400
|
+
logger.info("Running 'git init'...");
|
|
1401
|
+
await spawnInherited('git', ['init'], projectDir, 'screenci init');
|
|
1287
1402
|
}
|
|
1288
|
-
|
|
1289
|
-
spinner
|
|
1290
|
-
|
|
1403
|
+
else {
|
|
1404
|
+
const spinner = ora('Initializing git repository...').start();
|
|
1405
|
+
try {
|
|
1406
|
+
await spawnSilent('git', ['init'], projectDir);
|
|
1407
|
+
spinner.succeed('Git repository initialized');
|
|
1408
|
+
}
|
|
1409
|
+
catch (err) {
|
|
1410
|
+
spinner.fail('git init failed');
|
|
1411
|
+
throw err;
|
|
1412
|
+
}
|
|
1291
1413
|
}
|
|
1292
1414
|
}
|
|
1293
|
-
if (
|
|
1294
|
-
logger.info(
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
const spinner = ora('Running npm install...').start();
|
|
1299
|
-
try {
|
|
1300
|
-
await spawnSilent('npm', ['install', '--prefix', projectDir]);
|
|
1301
|
-
spinner.succeed('npm install complete');
|
|
1415
|
+
if (shouldInstallDependencies) {
|
|
1416
|
+
logger.info('screenci requires dependencies to be installed.');
|
|
1417
|
+
if (verbose) {
|
|
1418
|
+
logger.info(`Running '${skillsCommand}'...`);
|
|
1419
|
+
await spawnInherited('npx', skillsArgs, projectDir, 'screenci init');
|
|
1302
1420
|
}
|
|
1303
|
-
|
|
1304
|
-
spinner
|
|
1305
|
-
|
|
1421
|
+
else {
|
|
1422
|
+
const spinner = ora('Adding ScreenCI skills...').start();
|
|
1423
|
+
try {
|
|
1424
|
+
await spawnSilent('npx', skillsArgs, projectDir);
|
|
1425
|
+
spinner.succeed('ScreenCI skills added');
|
|
1426
|
+
}
|
|
1427
|
+
catch (err) {
|
|
1428
|
+
spinner.fail('ScreenCI skills install failed');
|
|
1429
|
+
throw err;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
if (verbose) {
|
|
1433
|
+
const installArgs = devScreenciPackageRoot
|
|
1434
|
+
? ['install', '--install-links']
|
|
1435
|
+
: ['install'];
|
|
1436
|
+
logger.info(`Running 'npm ${installArgs.join(' ')}'...`);
|
|
1437
|
+
await spawnInherited('npm', installArgs, projectDir, 'screenci init');
|
|
1438
|
+
}
|
|
1439
|
+
else {
|
|
1440
|
+
const spinner = ora('Running npm install...').start();
|
|
1441
|
+
try {
|
|
1442
|
+
const installArgs = devScreenciPackageRoot
|
|
1443
|
+
? ['install', '--install-links', '--prefix', projectDir]
|
|
1444
|
+
: ['install', '--prefix', projectDir];
|
|
1445
|
+
await spawnSilent('npm', installArgs);
|
|
1446
|
+
spinner.succeed('npm install complete');
|
|
1447
|
+
}
|
|
1448
|
+
catch (err) {
|
|
1449
|
+
spinner.fail('npm install failed');
|
|
1450
|
+
throw err;
|
|
1451
|
+
}
|
|
1306
1452
|
}
|
|
1453
|
+
logger.info("Local development requires Chromium for Playwright, running 'npx playwright install chromium --with-deps'...");
|
|
1454
|
+
await spawnInherited('npx', ['playwright', 'install', 'chromium', '--with-deps'], projectDir, 'screenci init');
|
|
1455
|
+
logger.info(`${pc.green('✔')} Playwright installed successfully`);
|
|
1456
|
+
}
|
|
1457
|
+
else {
|
|
1458
|
+
logger.info('Dependencies were not installed automatically.');
|
|
1459
|
+
logger.info('Run these commands when you are ready:');
|
|
1460
|
+
logger.info(` ${skillsCommand}`);
|
|
1461
|
+
logger.info(' npm install');
|
|
1462
|
+
logger.info(' npx playwright install chromium --with-deps');
|
|
1307
1463
|
}
|
|
1308
|
-
logger.info('Local development requires Chromium for Playwright.');
|
|
1309
|
-
logger.info("Running 'npx playwright install chromium --with-deps'...");
|
|
1310
|
-
await spawnInherited('npx', ['playwright', 'install', 'chromium', '--with-deps'], projectDir, 'screenci init');
|
|
1311
|
-
logger.info(`${pc.green('ok')} Playwright installed successfully`);
|
|
1312
1464
|
const cliDir = dirname(fileURLToPath(import.meta.url));
|
|
1313
1465
|
await buildRecordImages(requireContainerRuntime(), cliDir, resolve(projectDir, 'Dockerfile'), projectDir, verbose);
|
|
1314
1466
|
logger.info('');
|
|
@@ -1428,6 +1580,9 @@ export async function main() {
|
|
|
1428
1580
|
.action(async () => {
|
|
1429
1581
|
const parsed = parseConfigCliArgs(getSubcommandArgv('test'));
|
|
1430
1582
|
await run('test', parsed.otherArgs, parsed.configPath);
|
|
1583
|
+
if (process.env.SCREENCI_IN_CONTAINER === 'true')
|
|
1584
|
+
return;
|
|
1585
|
+
logger.info('Tests passed. Run `npx screenci record` to render the videos.');
|
|
1431
1586
|
});
|
|
1432
1587
|
program
|
|
1433
1588
|
.command('info')
|
|
@@ -1463,13 +1618,25 @@ export async function main() {
|
|
|
1463
1618
|
program
|
|
1464
1619
|
.command('init [name]')
|
|
1465
1620
|
.description('Initialize a new screenci project')
|
|
1621
|
+
.option('--git', 'initialize a git repository without prompting')
|
|
1622
|
+
.option('--install', 'install skills, dependencies, and Chromium without prompting')
|
|
1623
|
+
.option('--ci', 'add GitHub Action CI without prompting')
|
|
1624
|
+
.option('--skill', 'enable playwright-cli without prompting')
|
|
1625
|
+
.option('-y, --yes', 'answer yes to all init prompts')
|
|
1466
1626
|
.option('-v, --verbose', 'verbose output')
|
|
1467
1627
|
.action(async (name, options) => {
|
|
1468
1628
|
if (name === 'auth') {
|
|
1469
1629
|
await runInitAuth();
|
|
1470
1630
|
}
|
|
1471
1631
|
else {
|
|
1472
|
-
await runInit(name,
|
|
1632
|
+
await runInit(name, {
|
|
1633
|
+
verbose: options['verbose'] ?? false,
|
|
1634
|
+
git: options['git'] ?? false,
|
|
1635
|
+
install: options['install'] ?? false,
|
|
1636
|
+
yes: options['yes'] ?? false,
|
|
1637
|
+
skill: options['skill'] ?? false,
|
|
1638
|
+
ci: options['ci'] ?? false,
|
|
1639
|
+
});
|
|
1473
1640
|
}
|
|
1474
1641
|
});
|
|
1475
1642
|
try {
|
|
@@ -1834,6 +2001,12 @@ async function run(command, additionalArgs, customConfigPath) {
|
|
|
1834
2001
|
logger.info(`Running ScreenCI ${mode} with npx...`);
|
|
1835
2002
|
logger.info(`Using config: ${configPath}`);
|
|
1836
2003
|
}
|
|
2004
|
+
const devScreenciPackageRoot = getDevScreenciPackageRoot();
|
|
2005
|
+
if (devScreenciPackageRoot) {
|
|
2006
|
+
const configDir = dirname(configPath);
|
|
2007
|
+
await buildLocalScreenciPackage(devScreenciPackageRoot);
|
|
2008
|
+
await installLocalScreenciPackage(configDir, devScreenciPackageRoot);
|
|
2009
|
+
}
|
|
1837
2010
|
const playwrightArgs = [
|
|
1838
2011
|
'playwright',
|
|
1839
2012
|
'test',
|