Files
dh-inspeccion-v2/.github/workflows/f3-1-ci.yml
T

206 lines
7.3 KiB
YAML

name: F3.1 Inventory CI
on:
push:
branches:
- 'feature/f3-1*'
workflow_dispatch:
permissions:
contents: read
jobs:
api:
runs-on: ubuntu-latest
timeout-minutes: 25
defaults:
run:
working-directory: api-v3
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: npm
cache-dependency-path: api-v3/package-lock.json
- run: npm ci
- name: Typecheck
run: npm run typecheck 2>&1 | tee typecheck.log
- name: Tests
run: npm test 2>&1 | tee test.log
- name: Build
run: npm run build 2>&1 | tee build.log
- name: Diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: f3-1-api-diagnostics
path: |
api-v3/typecheck.log
api-v3/test.log
api-v3/build.log
if-no-files-found: warn
retention-days: 3
migrations:
name: DB · F3.1 on PostgreSQL 16/PostGIS
runs-on: ubuntu-latest
timeout-minutes: 30
services:
postgres:
image: postgis/postgis:16-3.4
env:
POSTGRES_USER: dhv2_owner
POSTGRES_PASSWORD: owner_test_password
POSTGRES_DB: dhv2_ci
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U dhv2_owner -d dhv2_ci"
--health-interval 5s
--health-timeout 5s
--health-retries 20
env:
DB_HOST: 127.0.0.1
DB_PORT: 5432
DB_NAME: dhv2_ci
DB_MIGRATION_USER: dhv2_owner
DB_MIGRATION_PASSWORD: owner_test_password
DB_APP_USER: dhv2_app
defaults:
run:
working-directory: api-v3
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: npm
cache-dependency-path: api-v3/package-lock.json
- name: PostgreSQL client
run: |
command -v psql >/dev/null || {
sudo apt-get update
sudo apt-get install -y postgresql-client
}
- name: Prepare roles and extensions
env:
PGPASSWORD: owner_test_password
run: |
psql -v ON_ERROR_STOP=1 -h 127.0.0.1 -U dhv2_owner -d dhv2_ci <<'SQL'
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname='dhv2_app') THEN
CREATE ROLE dhv2_app LOGIN PASSWORD 'app_test_password';
END IF;
END
$$;
GRANT CONNECT ON DATABASE dhv2_ci TO dhv2_app;
GRANT USAGE ON SCHEMA public TO dhv2_app;
CREATE TABLE IF NOT EXISTS typeorm_migrations (
id SERIAL PRIMARY KEY,
timestamp bigint NOT NULL,
name varchar NOT NULL
);
INSERT INTO typeorm_migrations (timestamp,name)
VALUES (1788652800000,'ResetProductionOperationalData1788652800000');
SQL
- run: npm ci
- run: npm run build
- name: Run every pending migration
run: npm run migration:run
- name: Assert no pending migrations
run: |
npm run migration:show | tee /tmp/migrations.txt
grep -Fq 'Pending migrations: no' /tmp/migrations.txt
- name: Assert F3.1 structure, merges and Inspector profile
env:
PGPASSWORD: owner_test_password
run: |
set -Eeuo pipefail
query() {
psql -At -v ON_ERROR_STOP=1 \
-h 127.0.0.1 \
-U dhv2_owner \
-d dhv2_ci \
-c "$1"
}
assert_eq() {
local expected="$1"
local sql="$2"
local actual
actual="$(query "$sql")"
if [ "$actual" != "$expected" ]; then
echo "ASSERT FAILED"
echo "SQL: $sql"
echo "Expected: $expected"
echo "Actual: $actual"
exit 1
fi
}
assert_eq 15 "SELECT count(*) FROM inventory_families WHERE level='INSTALLATION' AND is_active=true"
assert_eq 124 "SELECT count(*) FROM inventory_families WHERE level='SUBINSTALLATION' AND is_active=true"
assert_eq 16 "SELECT count(*) FROM inventory_families WHERE source_reference LIKE 'SYSTEM:F3.1:OTHER%'"
assert_eq 1 "SELECT count(*) FROM finding_categories WHERE lower(code)='app26r2' AND is_active=true"
assert_eq 1 "SELECT count(*) FROM finding_categories WHERE lower(code)='app26' AND is_active=false"
assert_eq 1 "SELECT count(*) FROM information_schema.tables WHERE table_name='asset_merges'"
assert_eq 1 "SELECT count(*) FROM pg_trigger WHERE tgname='trg_asset_merges_append_only' AND NOT tgisinternal"
assert_eq 1 "SELECT count(*) FROM information_schema.tables WHERE table_name='finding_catalog_item_merges'"
assert_eq 1 "SELECT count(*) FROM pg_trigger WHERE tgname='trg_finding_catalog_item_merges_append_only' AND NOT tgisinternal"
assert_eq 4 "SELECT count(*) FROM information_schema.columns WHERE table_name='users' AND column_name IN ('dni','phone','job_title','employee_number')"
assert_eq 2 "SELECT count(*) FROM pg_trigger WHERE tgname IN ('trg_user_roles_inspector_email','trg_users_inspector_email') AND NOT tgisinternal"
assert_eq 1 "SELECT count(*) FROM information_schema.columns WHERE table_name='inspection_document_deliveries' AND column_name='recipient_user_id'"
assert_eq 1 "SELECT count(*) FROM pg_constraint WHERE conname='chk_inspection_document_deliveries_recipient_kind' AND pg_get_constraintdef(oid) LIKE '%INSPECTOR%'"
assert_eq 1 "SELECT count(*) FROM pg_constraint WHERE conname='fk_inspection_document_deliveries_recipient_user'"
assert_eq 230 "SELECT count(*) FROM assets a JOIN asset_types t ON t.id=a.asset_type_id WHERE a.data_origin='IMPORT' AND a.source_name='Tablas de yacimiento(1).xlsx' AND lower(t.code)='yacimiento'"
assert_eq 0 "SELECT count(*) FROM assets WHERE (operational_area_id IS NULL) <> (operator_company_id IS NULL)"
web:
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: web-v2
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: npm
cache-dependency-path: web-v2/package-lock.json
- run: npm ci
- name: Typecheck
run: npm run typecheck 2>&1 | tee typecheck.log
- name: Build
run: npm run build 2>&1 | tee build.log
- name: Diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: f3-1-web-diagnostics
path: |
web-v2/typecheck.log
web-v2/build.log
if-no-files-found: warn
retention-days: 3
docker:
needs: [api, web, migrations]
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- name: Validate Compose
run: docker compose --env-file .env.example config >/dev/null
- name: Build production images
run: docker compose --env-file .env.example build api migrate web