Enhance Git LFS validation in CI workflow and update Docker Compose configuration
Some checks failed
Publish FaceAI Container / publish (push) Failing after 4s

This commit is contained in:
MaddoScientisto 2026-04-19 12:10:18 +02:00
commit f19b8e20ff
5 changed files with 63 additions and 5 deletions

View file

@ -28,6 +28,8 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
lfs: true
- name: Validate workflow variables - name: Validate workflow variables
run: | run: |
@ -41,6 +43,34 @@ jobs:
if [ ! -f "faceai/package.json" ]; then echo "faceai/package.json is missing from the repository checkout"; exit 1; fi if [ ! -f "faceai/package.json" ]; then echo "faceai/package.json is missing from the repository checkout"; exit 1; fi
if [ ! -f "bin/Face_Recognition_Unix/face_matcher" ]; then echo "bin/Face_Recognition_Unix/face_matcher is missing from the repository checkout"; exit 1; fi if [ ! -f "bin/Face_Recognition_Unix/face_matcher" ]; then echo "bin/Face_Recognition_Unix/face_matcher is missing from the repository checkout"; exit 1; fi
- name: Validate Git LFS checkout for matcher binary
run: |
set -eu
if ! command -v git >/dev/null 2>&1; then
echo "git is required to validate Git LFS checkout"
exit 1
fi
if ! git lfs version >/dev/null 2>&1; then
echo "git-lfs is required on the runner so the processor image can include the real matcher binary"
exit 1
fi
git lfs pull --include="bin/Face_Recognition_Unix/face_matcher"
if grep -q "https://git-lfs.github.com/spec/v1" bin/Face_Recognition_Unix/face_matcher; then
echo "bin/Face_Recognition_Unix/face_matcher is still an LFS pointer, not the real binary"
exit 1
fi
MATCHER_SIZE="$(wc -c < bin/Face_Recognition_Unix/face_matcher | tr -d '[:space:]')"
if [ "${MATCHER_SIZE}" -lt 1000000 ]; then
echo "bin/Face_Recognition_Unix/face_matcher is unexpectedly small (${MATCHER_SIZE} bytes) and does not look like the real binary"
exit 1
fi
echo "Validated Git LFS checkout for matcher binary (${MATCHER_SIZE} bytes)"
- name: Validate registry secrets - name: Validate registry secrets
run: | run: |
set -eu set -eu

View file

@ -75,7 +75,6 @@ services:
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS: 5000 FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS: 5000
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS: 20 FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS: 20
volumes: volumes:
- .:/app
- ./logs:/data/logs - ./logs:/data/logs
- ../test_pkl:/data/pkl:ro - ../test_pkl:/data/pkl:ro
- faceai-runtime:/data/runtime - faceai-runtime:/data/runtime

View file

@ -166,7 +166,7 @@ test('shows the unsupported-race message when the current race has no PKL data a
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
await expect(page).toHaveURL(FACEAI_HOME_URL_RE); await expect(page).toHaveURL(FACEAI_HOME_URL_RE);
await page.getByRole('link', { name: 'Torna alla pagina gara' }).click(); await page.getByRole('button', { name: 'Torna alla pagina gara' }).click();
await expect(page).toHaveURL(buildLegacySimulatorReturnMatcher('404')); await expect(page).toHaveURL(buildLegacySimulatorReturnMatcher('404'));
}); });
@ -198,7 +198,7 @@ test('shows a localized invalid-race error when session race data points to a mi
await expect(page.locator('input[type="file"]')).toBeDisabled(); await expect(page.locator('input[type="file"]')).toBeDisabled();
await expect(page.getByRole('button', { name: 'Choose image' })).toBeDisabled(); await expect(page.getByRole('button', { name: 'Choose image' })).toBeDisabled();
await expect(page.getByRole('button', { name: 'Start Face ID search' })).toHaveCount(0); await expect(page.getByRole('button', { name: 'Start Face ID search' })).toHaveCount(0);
await expect(page.getByRole('link', { name: 'Back to the race page' })).toBeVisible(); await expect(page.getByRole('button', { name: 'Back to the race page' })).toBeVisible();
await expect.poll(() => { await expect.poll(() => {
return consoleErrors.find((entry) => entry.includes('[FaceAI] Invalid race data:')) || null; return consoleErrors.find((entry) => entry.includes('[FaceAI] Invalid race data:')) || null;
}).toContain('RACE_DIRECTORY_NOT_FOUND'); }).toContain('RACE_DIRECTORY_NOT_FOUND');
@ -206,7 +206,7 @@ test('shows a localized invalid-race error when session race data points to a mi
return consoleErrors.find((entry) => entry.includes('[FaceAI] Invalid race data:')) || null; return consoleErrors.find((entry) => entry.includes('[FaceAI] Invalid race data:')) || null;
}).toContain('THIS RACE DOES NOT EXIST'); }).toContain('THIS RACE DOES NOT EXIST');
await page.getByRole('link', { name: 'Back to the race page' }).click(); await page.getByRole('button', { name: 'Back to the race page' }).click();
await expect(page).toHaveURL(buildLegacySimulatorReturnMatcher('405')); await expect(page).toHaveURL(buildLegacySimulatorReturnMatcher('405'));
}); });
@ -262,7 +262,7 @@ test('shows the no-face message and allows the user to return to the race page',
expectedSelfieName: 'DSC_1994.JPG' expectedSelfieName: 'DSC_1994.JPG'
}); });
await page.getByRole('link', { name: 'Torna alla pagina gara' }).click(); await page.getByRole('button', { name: 'Torna alla pagina gara' }).click();
await expect(page).toHaveURL(buildLegacySimulatorReturnMatcher('202')); await expect(page).toHaveURL(buildLegacySimulatorReturnMatcher('202'));
}); });

View file

@ -121,6 +121,31 @@ test('launches the live FaceAI app with race storage metadata and a styled heade
expect(consoleErrors.find((entry) => entry.includes('[FaceAI] Invalid race data:')) || '').toBe(''); expect(consoleErrors.find((entry) => entry.includes('[FaceAI] Invalid race data:')) || '').toBe('');
}); });
test('returns to the live race page from FaceAI without leaving the legacy spinner stuck', async ({ page }) => {
await openLiveFaceAi(page);
await page.getByRole('button', { name: /Torna alla pagina gara|Back to the race page/i }).click();
await page.waitForURL((url) => {
return url.toString().startsWith(LIVE_SITE_BASE_URL) && !url.toString().startsWith(LIVE_FACEAI_BASE_URL);
}, {
timeout: 60 * 1000
});
await expect(page.locator('form[onsubmit="return searching()"]')).toBeVisible();
await expect(page.locator('#faceaiLaunchButton')).toBeVisible();
const bodyState = await page.locator('body').evaluate((element) => {
return {
className: element.className,
ariaBusy: element.getAttribute('aria-busy')
};
});
expect(bodyState.className).not.toContain('loading');
expect(bodyState.ariaBusy).not.toBe('true');
});
test.skip(!LIVE_SITE_RUN_UPLOAD_FLOW, 'Set LIVE_SITE_RUN_UPLOAD_FLOW=1 to exercise the live upload flow.'); test.skip(!LIVE_SITE_RUN_UPLOAD_FLOW, 'Set LIVE_SITE_RUN_UPLOAD_FLOW=1 to exercise the live upload flow.');
test('accepts the supplied portrait image for the live upload flow', async ({ page }) => { test('accepts the supplied portrait image for the live upload flow', async ({ page }) => {

View file

@ -0,0 +1,4 @@
{
"status": "failed",
"failedTests": []
}